@rimelight/seo 0.0.4 → 0.0.5
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/index.d.mts +6 -38
- package/dist/index.mjs +5 -176
- package/dist/integration.d.mts +23 -0
- package/dist/integration.mjs +33 -0
- package/dist/llms-BVLxzjr-.d.mts +41 -0
- package/dist/llms.d.mts +2 -0
- package/dist/llms.mjs +75 -0
- package/dist/meta.d.mts +42 -0
- package/dist/meta.mjs +66 -0
- package/dist/robots.d.mts +3 -4
- package/dist/routes/llms.txt.d.mts +4 -0
- package/dist/routes/llms.txt.mjs +20 -0
- package/dist/routes/robots.txt.d.mts +4 -0
- package/dist/routes/robots.txt.mjs +18 -0
- package/dist/routes/sitemap.xml.d.mts +4 -0
- package/dist/routes/sitemap.xml.mjs +13 -0
- package/dist/schema-C8v69blQ.d.mts +28 -0
- package/dist/schema.d.mts +2 -0
- package/dist/schema.mjs +52 -0
- package/dist/sitemap.d.mts +6 -7
- package/dist/types.d.mts +277 -2
- package/package.json +9 -4
- package/src/components/SEOHead.astro +65 -18
- package/src/env.d.ts +5 -0
- package/src/index.ts +5 -1
- package/src/integration.ts +74 -0
- package/src/meta.test.ts +25 -1
- package/src/meta.ts +32 -2
- package/src/routes/llms.txt.ts +22 -0
- package/src/routes/robots.txt.ts +20 -0
- package/src/routes/sitemap.xml.ts +16 -0
- package/src/types.ts +39 -0
- package/dist/types-e7gqYZwc.d.mts +0 -305
package/src/meta.ts
CHANGED
|
@@ -12,19 +12,49 @@ export function buildCanonicalUrl(url: string | URL, base: string | URL): string
|
|
|
12
12
|
return path.includes("?") ? path.replace(/\/?$/, "") : path.replace(/\/?$/, "/")
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Deep merge two metadata or configuration objects.
|
|
17
|
+
*/
|
|
18
|
+
export function deepMerge<T extends Record<string, any>>(
|
|
19
|
+
base: T,
|
|
20
|
+
override?: Record<string, any>
|
|
21
|
+
): T {
|
|
22
|
+
if (!override) return { ...base }
|
|
23
|
+
const result: Record<string, any> = { ...base }
|
|
24
|
+
for (const key of Object.keys(override)) {
|
|
25
|
+
const baseVal = base[key]
|
|
26
|
+
const overrideVal = override[key]
|
|
27
|
+
if (
|
|
28
|
+
baseVal &&
|
|
29
|
+
overrideVal &&
|
|
30
|
+
typeof baseVal === "object" &&
|
|
31
|
+
typeof overrideVal === "object" &&
|
|
32
|
+
!Array.isArray(baseVal) &&
|
|
33
|
+
!Array.isArray(overrideVal)
|
|
34
|
+
) {
|
|
35
|
+
result[key] = deepMerge(baseVal, overrideVal)
|
|
36
|
+
} else if (overrideVal !== undefined) {
|
|
37
|
+
result[key] = overrideVal
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result as T
|
|
41
|
+
}
|
|
42
|
+
|
|
15
43
|
/**
|
|
16
44
|
* Build a page title using a site's title template. Falls back to siteName for untitled pages; uses
|
|
17
|
-
* a 404 label for error pages.
|
|
45
|
+
* a 404 label for error pages. Supports absolute title bypass.
|
|
18
46
|
*/
|
|
19
47
|
export function buildPageTitle(opts: {
|
|
20
48
|
title?: string
|
|
21
49
|
siteName: string
|
|
22
50
|
titleTemplate: string
|
|
23
51
|
is404?: boolean
|
|
52
|
+
absolute?: boolean
|
|
24
53
|
}): string {
|
|
25
|
-
const { title, siteName, titleTemplate, is404 } = opts
|
|
54
|
+
const { title, siteName, titleTemplate, is404, absolute } = opts
|
|
26
55
|
if (is404) return `404 - Not Found | ${siteName}`
|
|
27
56
|
if (!title) return siteName
|
|
57
|
+
if (absolute) return title
|
|
28
58
|
return titleTemplate.replace("%s", title)
|
|
29
59
|
}
|
|
30
60
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { APIRoute } from "astro"
|
|
2
|
+
import { buildLlmsTxt } from "../llms.js"
|
|
3
|
+
import seoConfig from "virtual:rimelight-seo-config"
|
|
4
|
+
|
|
5
|
+
export const GET: APIRoute = ({ site }) => {
|
|
6
|
+
const llmsOpts = typeof seoConfig?.llms === "object" ? seoConfig.llms : {}
|
|
7
|
+
const siteStr = site ? site.toString().replace(/\/$/, "") : ""
|
|
8
|
+
const hostname = site ? new URL(site).hostname : "Site"
|
|
9
|
+
const content = buildLlmsTxt({
|
|
10
|
+
site: siteStr,
|
|
11
|
+
title: hostname,
|
|
12
|
+
pages: [],
|
|
13
|
+
...llmsOpts
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
return new Response(content, {
|
|
17
|
+
headers: {
|
|
18
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
19
|
+
"Cache-Control": "public, max-age=3600, stale-while-revalidate=86400"
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { APIRoute } from "astro"
|
|
2
|
+
import { buildRobotsTxt } from "../robots.js"
|
|
3
|
+
import seoConfig from "virtual:rimelight-seo-config"
|
|
4
|
+
|
|
5
|
+
export const GET: APIRoute = ({ site }) => {
|
|
6
|
+
const sitemapURL = site ? new URL("sitemap.xml", site).toString() : ""
|
|
7
|
+
const robotsOpts = typeof seoConfig?.robots === "object" ? seoConfig.robots : {}
|
|
8
|
+
const robots = buildRobotsTxt({
|
|
9
|
+
sitemapUrl: sitemapURL,
|
|
10
|
+
allow: ["/"],
|
|
11
|
+
...robotsOpts
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
return new Response(robots, {
|
|
15
|
+
headers: {
|
|
16
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
17
|
+
"Cache-Control": "public, max-age=3600, stale-while-revalidate=86400"
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { APIRoute } from "astro"
|
|
2
|
+
import { buildSitemapXml } from "../sitemap.js"
|
|
3
|
+
import seoConfig from "virtual:rimelight-seo-config"
|
|
4
|
+
|
|
5
|
+
export const GET: APIRoute = () => {
|
|
6
|
+
const sitemapOpts = typeof seoConfig?.sitemap === "object" ? seoConfig.sitemap : {}
|
|
7
|
+
const urls = sitemapOpts.urls || []
|
|
8
|
+
const xml = buildSitemapXml(urls)
|
|
9
|
+
|
|
10
|
+
return new Response(xml, {
|
|
11
|
+
headers: {
|
|
12
|
+
"Content-Type": "application/xml; charset=utf-8",
|
|
13
|
+
"Cache-Control": "public, max-age=3600, stale-while-revalidate=86400"
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -90,6 +90,27 @@ export interface UserAgentRule {
|
|
|
90
90
|
allow?: string[]
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
export interface OpenGraphMeta {
|
|
94
|
+
type?: string
|
|
95
|
+
locale?: string
|
|
96
|
+
url?: string
|
|
97
|
+
title?: string
|
|
98
|
+
description?: string
|
|
99
|
+
images?: OGImage[] | OGImage
|
|
100
|
+
siteName?: string
|
|
101
|
+
[key: string]: unknown
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface TwitterMeta {
|
|
105
|
+
card?: "summary" | "summary_large_image" | "player" | "app"
|
|
106
|
+
site?: string
|
|
107
|
+
creator?: string
|
|
108
|
+
title?: string
|
|
109
|
+
description?: string
|
|
110
|
+
images?: OGImage[] | OGImage | string
|
|
111
|
+
[key: string]: unknown
|
|
112
|
+
}
|
|
113
|
+
|
|
93
114
|
/**
|
|
94
115
|
* Site identity and SEO defaults shared across all Rimelight Astro sites. The UI-specific overrides
|
|
95
116
|
* (component themes, shortcuts, etc.) live in UIConfig (packages/ui) and are passed directly to the
|
|
@@ -121,6 +142,8 @@ export interface SiteConfig {
|
|
|
121
142
|
maxDescriptionLength: number
|
|
122
143
|
authorHandle?: string
|
|
123
144
|
}
|
|
145
|
+
openGraph?: OpenGraphMeta
|
|
146
|
+
twitter?: TwitterMeta
|
|
124
147
|
}
|
|
125
148
|
|
|
126
149
|
/**
|
|
@@ -236,6 +259,22 @@ export interface HeadProps {
|
|
|
236
259
|
* Version alternates for multi-version documentation
|
|
237
260
|
*/
|
|
238
261
|
versionAlternates?: Array<{ version: string; href: string }>
|
|
262
|
+
/**
|
|
263
|
+
* Whether the title should bypass site title template
|
|
264
|
+
*/
|
|
265
|
+
absolute?: boolean
|
|
266
|
+
/**
|
|
267
|
+
* Twitter card type
|
|
268
|
+
*/
|
|
269
|
+
twitterCard?: "summary" | "summary_large_image" | "player" | "app"
|
|
270
|
+
/**
|
|
271
|
+
* Open Graph metadata overrides
|
|
272
|
+
*/
|
|
273
|
+
openGraph?: OpenGraphMeta
|
|
274
|
+
/**
|
|
275
|
+
* Twitter metadata overrides
|
|
276
|
+
*/
|
|
277
|
+
twitter?: TwitterMeta
|
|
239
278
|
}
|
|
240
279
|
|
|
241
280
|
export type { LlmsPage, LlmsTxtOptions, LlmsFullTxtOptions } from "./llms.js"
|
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
//#region src/schema.d.ts
|
|
2
|
-
interface ArticleSchemaOptions {
|
|
3
|
-
type?: "TechArticle" | "Article" | "BlogPosting";
|
|
4
|
-
title: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
url: string;
|
|
7
|
-
datePublished?: string | Date;
|
|
8
|
-
dateModified?: string | Date;
|
|
9
|
-
authorName?: string;
|
|
10
|
-
authorUrl?: string;
|
|
11
|
-
image?: string;
|
|
12
|
-
publisherName?: string;
|
|
13
|
-
publisherLogo?: string;
|
|
14
|
-
}
|
|
15
|
-
interface BreadcrumbItem {
|
|
16
|
-
name: string;
|
|
17
|
-
url: string;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Builds Schema.org Article / TechArticle / BlogPosting JSON-LD.
|
|
21
|
-
*/
|
|
22
|
-
declare function buildArticleSchema(options: ArticleSchemaOptions): Record<string, any>;
|
|
23
|
-
/**
|
|
24
|
-
* Builds Schema.org BreadcrumbList JSON-LD.
|
|
25
|
-
*/
|
|
26
|
-
declare function buildBreadcrumbSchema(items: BreadcrumbItem[]): Record<string, any>;
|
|
27
|
-
//#endregion
|
|
28
|
-
//#region src/llms.d.ts
|
|
29
|
-
interface LlmsPage {
|
|
30
|
-
title: string;
|
|
31
|
-
url: string;
|
|
32
|
-
description?: string;
|
|
33
|
-
markdownUrl?: string;
|
|
34
|
-
section?: string;
|
|
35
|
-
}
|
|
36
|
-
interface LlmsTxtOptions {
|
|
37
|
-
site: string;
|
|
38
|
-
title: string;
|
|
39
|
-
description?: string;
|
|
40
|
-
fullCorpusUrl?: string;
|
|
41
|
-
pages: LlmsPage[];
|
|
42
|
-
sections?: Array<{
|
|
43
|
-
label: string;
|
|
44
|
-
url: string;
|
|
45
|
-
}>;
|
|
46
|
-
}
|
|
47
|
-
interface LlmsFullTxtOptions {
|
|
48
|
-
site: string;
|
|
49
|
-
title: string;
|
|
50
|
-
description?: string;
|
|
51
|
-
pages: Array<{
|
|
52
|
-
title: string;
|
|
53
|
-
url: string;
|
|
54
|
-
description?: string;
|
|
55
|
-
markdown: string;
|
|
56
|
-
version?: string;
|
|
57
|
-
}>;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Builds standard /llms.txt document format for AI discovery.
|
|
61
|
-
*/
|
|
62
|
-
declare function buildLlmsTxt(options: LlmsTxtOptions): string;
|
|
63
|
-
/**
|
|
64
|
-
* Builds concatenated /llms-full.txt single corpus document for AI agents.
|
|
65
|
-
*/
|
|
66
|
-
declare function buildLlmsFullTxt(options: LlmsFullTxtOptions): string;
|
|
67
|
-
//#endregion
|
|
68
|
-
//#region src/types.d.ts
|
|
69
|
-
/**
|
|
70
|
-
* Change frequency for sitemap entries
|
|
71
|
-
*/
|
|
72
|
-
type ChangeFreq = "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
|
|
73
|
-
/**
|
|
74
|
-
* SEO entry — a single page to include in sitemaps
|
|
75
|
-
*/
|
|
76
|
-
interface SeoEntry {
|
|
77
|
-
/**
|
|
78
|
-
* Locale-less path, e.g. "/company/blog/hello". Leading slash required.
|
|
79
|
-
*/
|
|
80
|
-
path: string;
|
|
81
|
-
lastmod?: Date;
|
|
82
|
-
changefreq?: ChangeFreq;
|
|
83
|
-
priority?: number;
|
|
84
|
-
/**
|
|
85
|
-
* Restrict to a subset of locales; defaults to all configured locales.
|
|
86
|
-
*/
|
|
87
|
-
locales?: readonly string[];
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Locale configuration for SEO builders
|
|
91
|
-
*/
|
|
92
|
-
interface LocaleConfig {
|
|
93
|
-
/**
|
|
94
|
-
* Absolute origin, e.g. "https://rimelight.com"
|
|
95
|
-
*/
|
|
96
|
-
site: string;
|
|
97
|
-
/**
|
|
98
|
-
* Map of locale segment -> hreflang, e.g. { en: "en-US", pt: "pt-BR" }
|
|
99
|
-
*/
|
|
100
|
-
locales: Record<string, string>;
|
|
101
|
-
defaultLocale: string;
|
|
102
|
-
/**
|
|
103
|
-
* Emit the default locale without a prefix. Default: false.
|
|
104
|
-
*/
|
|
105
|
-
prefixDefaultLocale?: boolean;
|
|
106
|
-
trailingSlash?: "always" | "never";
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Fully resolved sitemap URL with alternates
|
|
110
|
-
*/
|
|
111
|
-
interface SitemapUrl {
|
|
112
|
-
loc: string;
|
|
113
|
-
lastmod?: string;
|
|
114
|
-
changefreq?: ChangeFreq;
|
|
115
|
-
priority?: number;
|
|
116
|
-
alternates?: SitemapAlternate[];
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Language alternate for a sitemap URL
|
|
120
|
-
*/
|
|
121
|
-
interface SitemapAlternate {
|
|
122
|
-
hreflang: string;
|
|
123
|
-
href: string;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Options for robots.txt generation
|
|
127
|
-
*/
|
|
128
|
-
interface RobotsOptions {
|
|
129
|
-
/**
|
|
130
|
-
* The sitemap URL to reference
|
|
131
|
-
*/
|
|
132
|
-
sitemapUrl: string;
|
|
133
|
-
/**
|
|
134
|
-
* Paths to disallow for all user agents
|
|
135
|
-
*/
|
|
136
|
-
disallow?: string[];
|
|
137
|
-
/**
|
|
138
|
-
* Paths to allow for all user agents
|
|
139
|
-
*/
|
|
140
|
-
allow?: string[];
|
|
141
|
-
/**
|
|
142
|
-
* User-agent specific rules
|
|
143
|
-
*/
|
|
144
|
-
userAgentRules?: UserAgentRule[];
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* User-agent specific robots.txt rule
|
|
148
|
-
*/
|
|
149
|
-
interface UserAgentRule {
|
|
150
|
-
userAgent: string;
|
|
151
|
-
disallow?: string[];
|
|
152
|
-
allow?: string[];
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Site identity and SEO defaults shared across all Rimelight Astro sites. The UI-specific overrides
|
|
156
|
-
* (component themes, shortcuts, etc.) live in UIConfig (packages/ui) and are passed directly to the
|
|
157
|
-
* ui() integration.
|
|
158
|
-
*/
|
|
159
|
-
interface SiteConfig {
|
|
160
|
-
id: string;
|
|
161
|
-
name: string;
|
|
162
|
-
description: string;
|
|
163
|
-
url: string;
|
|
164
|
-
ogImage: string;
|
|
165
|
-
author: string;
|
|
166
|
-
email: string;
|
|
167
|
-
branding: {
|
|
168
|
-
logo: {
|
|
169
|
-
alt: string;
|
|
170
|
-
};
|
|
171
|
-
favicon: {
|
|
172
|
-
svg: string;
|
|
173
|
-
};
|
|
174
|
-
colors: {
|
|
175
|
-
themeColor: string;
|
|
176
|
-
backgroundColor: string;
|
|
177
|
-
};
|
|
178
|
-
};
|
|
179
|
-
seo: {
|
|
180
|
-
titleTemplate: string;
|
|
181
|
-
ogImageFallback: string;
|
|
182
|
-
maxDescriptionLength: number;
|
|
183
|
-
authorHandle?: string;
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Open Graph image with alt text
|
|
188
|
-
*/
|
|
189
|
-
interface OGImage {
|
|
190
|
-
/**
|
|
191
|
-
* Image URL (relative or absolute)
|
|
192
|
-
*/
|
|
193
|
-
src: string;
|
|
194
|
-
/**
|
|
195
|
-
* Alt text for the image
|
|
196
|
-
*/
|
|
197
|
-
alt: string;
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* RSS feed link configuration
|
|
201
|
-
*/
|
|
202
|
-
interface RSSFeed {
|
|
203
|
-
/**
|
|
204
|
-
* RSS feed URL
|
|
205
|
-
*/
|
|
206
|
-
href: string;
|
|
207
|
-
/**
|
|
208
|
-
* Feed title (defaults to "RSS")
|
|
209
|
-
*/
|
|
210
|
-
title?: string;
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Props for the RLAHead Astro component. Defined here so consumers can construct head props without
|
|
214
|
-
* importing @rimelight/ui.
|
|
215
|
-
*/
|
|
216
|
-
interface HeadProps {
|
|
217
|
-
/**
|
|
218
|
-
* Page title
|
|
219
|
-
*/
|
|
220
|
-
title?: string;
|
|
221
|
-
/**
|
|
222
|
-
* Page description
|
|
223
|
-
*/
|
|
224
|
-
description?: string;
|
|
225
|
-
/**
|
|
226
|
-
* Open Graph image with alt text
|
|
227
|
-
*/
|
|
228
|
-
ogImage?: OGImage;
|
|
229
|
-
/**
|
|
230
|
-
* Open Graph type (e.g., "website", "article")
|
|
231
|
-
*/
|
|
232
|
-
ogType?: string;
|
|
233
|
-
/**
|
|
234
|
-
* Open Graph locale (defaults to "en_US")
|
|
235
|
-
*/
|
|
236
|
-
ogLocale?: string;
|
|
237
|
-
/**
|
|
238
|
-
* Whether to prevent indexing
|
|
239
|
-
*/
|
|
240
|
-
noindex?: boolean;
|
|
241
|
-
/**
|
|
242
|
-
* Whether this is a 404 page
|
|
243
|
-
*/
|
|
244
|
-
is404?: boolean;
|
|
245
|
-
/**
|
|
246
|
-
* Robots metadata (overrides noindex/is404 logic if provided)
|
|
247
|
-
*/
|
|
248
|
-
robots?: string;
|
|
249
|
-
/**
|
|
250
|
-
* Canonical URL
|
|
251
|
-
*/
|
|
252
|
-
canonical?: string;
|
|
253
|
-
/**
|
|
254
|
-
* Language alternates for i18n
|
|
255
|
-
*/
|
|
256
|
-
languageAlternates?: Array<{
|
|
257
|
-
hreflang: string;
|
|
258
|
-
href: string;
|
|
259
|
-
}>;
|
|
260
|
-
/**
|
|
261
|
-
* Custom favicon SVG or image path (overrides config.branding.favicon.svg)
|
|
262
|
-
*/
|
|
263
|
-
favicon?: string;
|
|
264
|
-
/**
|
|
265
|
-
* Site configuration for defaults
|
|
266
|
-
*/
|
|
267
|
-
config?: SiteConfig;
|
|
268
|
-
/**
|
|
269
|
-
* Whether to enable View Transitions (ClientRouter)
|
|
270
|
-
*/
|
|
271
|
-
transitions?: boolean;
|
|
272
|
-
/**
|
|
273
|
-
* Meta charset
|
|
274
|
-
*/
|
|
275
|
-
charset?: string;
|
|
276
|
-
/**
|
|
277
|
-
* Meta viewport
|
|
278
|
-
*/
|
|
279
|
-
viewport?: string;
|
|
280
|
-
/**
|
|
281
|
-
* RSS feed configuration
|
|
282
|
-
*/
|
|
283
|
-
rssFeed?: RSSFeed;
|
|
284
|
-
/**
|
|
285
|
-
* Article or BlogPosting JSON-LD configuration
|
|
286
|
-
*/
|
|
287
|
-
articleSchema?: ArticleSchemaOptions;
|
|
288
|
-
/**
|
|
289
|
-
* Breadcrumb list for JSON-LD structured data
|
|
290
|
-
*/
|
|
291
|
-
breadcrumbs?: BreadcrumbItem[];
|
|
292
|
-
/**
|
|
293
|
-
* URL for this page's raw Markdown alternate twin
|
|
294
|
-
*/
|
|
295
|
-
markdownUrl?: string;
|
|
296
|
-
/**
|
|
297
|
-
* Version alternates for multi-version documentation
|
|
298
|
-
*/
|
|
299
|
-
versionAlternates?: Array<{
|
|
300
|
-
version: string;
|
|
301
|
-
href: string;
|
|
302
|
-
}>;
|
|
303
|
-
}
|
|
304
|
-
//#endregion
|
|
305
|
-
export { ArticleSchemaOptions as _, RSSFeed as a, buildBreadcrumbSchema as b, SiteConfig as c, UserAgentRule as d, LlmsFullTxtOptions as f, buildLlmsTxt as g, buildLlmsFullTxt as h, OGImage as i, SitemapAlternate as l, LlmsTxtOptions as m, HeadProps as n, RobotsOptions as o, LlmsPage as p, LocaleConfig as r, SeoEntry as s, ChangeFreq as t, SitemapUrl as u, BreadcrumbItem as v, buildArticleSchema as y };
|