@pas7/nextjs-sitemap-hreflang 0.3.1

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.
@@ -0,0 +1,261 @@
1
+ type ChangeFrequency = "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
2
+ type SitemapAlternates = {
3
+ languages?: Record<string, string>;
4
+ };
5
+ type SitemapEntryLike = {
6
+ url: string;
7
+ lastModified?: string | Date;
8
+ changeFrequency?: ChangeFrequency;
9
+ priority?: number;
10
+ alternates?: SitemapAlternates;
11
+ images?: string[];
12
+ };
13
+ type SitemapEntry = SitemapEntryLike;
14
+ type XDefaultStrategy = {
15
+ type: "loc";
16
+ } | {
17
+ type: "root";
18
+ } | {
19
+ type: "locale";
20
+ locale: string;
21
+ } | {
22
+ type: "custom";
23
+ url: string;
24
+ } | {
25
+ type: "fn";
26
+ resolve: (entry: SitemapEntryLike) => string;
27
+ };
28
+ type HreflangIssueCode = "MISSING_LANGUAGES" | "MISSING_XDEFAULT" | "MISSING_SELF" | "NON_ABSOLUTE_URL" | "INVALID_LOCALE_KEY" | "DUPLICATE_HREFLANG_KEY" | "DUPLICATE_HREF" | "INVALID_HREFLANG_CASING" | "INCONSISTENT_ORIGIN";
29
+ type HreflangIssue = {
30
+ code: HreflangIssueCode;
31
+ entryUrl: string;
32
+ message: string;
33
+ };
34
+ type HreflangReport = {
35
+ ok: boolean;
36
+ issues: HreflangIssue[];
37
+ };
38
+ /**
39
+ * Routing strategy for generating hreflang URLs.
40
+ * This makes the package routing-agnostic.
41
+ */
42
+ type RoutingStrategy = {
43
+ /** Supported locales */
44
+ readonly locales: readonly string[];
45
+ /** Default/canonical locale */
46
+ readonly canonicalLocale: string;
47
+ /** Generate URL for a given pathname and locale */
48
+ readonly hrefFor: (args: {
49
+ pathname: string;
50
+ locale: string;
51
+ }) => string;
52
+ /** x-default strategy (optional) */
53
+ readonly xDefault?: XDefaultStrategy;
54
+ };
55
+ /**
56
+ * Options for prefix-as-needed routing (like next-intl)
57
+ */
58
+ type RoutingPrefixAsNeededOptions = {
59
+ readonly defaultLocale: string;
60
+ readonly locales: readonly string[];
61
+ readonly basePath?: string;
62
+ };
63
+ /**
64
+ * Options for prefix-always routing
65
+ */
66
+ type RoutingPrefixAlwaysOptions = {
67
+ readonly defaultLocale: string;
68
+ readonly locales: readonly string[];
69
+ readonly basePath?: string;
70
+ };
71
+ /**
72
+ * Options for domain-based routing
73
+ */
74
+ type RoutingDomainBasedOptions = {
75
+ readonly defaultLocale: string;
76
+ readonly locales: readonly string[];
77
+ readonly localeToDomain: Record<string, string>;
78
+ };
79
+ /**
80
+ * Options for suffix-locale routing (like /blog/uk)
81
+ */
82
+ type RoutingSuffixLocaleOptions = {
83
+ readonly defaultLocale: string;
84
+ readonly locales: readonly string[];
85
+ readonly basePath?: string;
86
+ };
87
+ /**
88
+ * Options for PAS7 custom routing scheme
89
+ */
90
+ type RoutingPAS7Options = {
91
+ readonly defaultLocale: string;
92
+ readonly locales: readonly string[];
93
+ readonly hubPaths?: readonly string[];
94
+ readonly detailPathPattern?: RegExp;
95
+ };
96
+
97
+ type ManifestRouteStyle = "prefix-as-needed" | "prefix-always" | "suffix-locale" | "locale-segment";
98
+ type LocalizedManifestItem = {
99
+ slug: string;
100
+ locales: readonly string[];
101
+ updatedAt?: string | Date;
102
+ publishedAt?: string | Date;
103
+ lastModified?: string | Date;
104
+ date?: string | Date;
105
+ changeFrequency?: ChangeFrequency;
106
+ priority?: number;
107
+ images?: string[];
108
+ };
109
+ type CreateSitemapEntriesFromManifestOptions = {
110
+ baseUrl: string;
111
+ sectionPath: string;
112
+ defaultLocale: string;
113
+ canonicalLocale?: string;
114
+ routeStyle?: ManifestRouteStyle;
115
+ trailingSlash?: "preserve" | "always" | "never";
116
+ ensureXDefault?: boolean;
117
+ xDefaultStrategy?: XDefaultStrategy;
118
+ includeLocales?: readonly string[];
119
+ pathnameFor?: (args: {
120
+ slug: string;
121
+ locale: string;
122
+ defaultLocale: string;
123
+ sectionPath: string;
124
+ routeStyle: ManifestRouteStyle;
125
+ }) => string;
126
+ };
127
+ declare function createSitemapEntriesFromManifest<T extends LocalizedManifestItem>(items: readonly T[], options: CreateSitemapEntriesFromManifestOptions): SitemapEntry[];
128
+
129
+ type BuildLanguagesMapInput = {
130
+ baseUrl: string;
131
+ locales: readonly string[];
132
+ canonicalLocale: string;
133
+ resolveHref: (locale: string) => string;
134
+ includeXDefault: boolean;
135
+ xDefaultStrategy?: XDefaultStrategy;
136
+ trailingSlash?: "preserve" | "always" | "never";
137
+ };
138
+ type BuildLanguagesMapOutput = {
139
+ canonical: string;
140
+ languages: Record<string, string>;
141
+ };
142
+ declare function buildLanguagesMap(input: BuildLanguagesMapInput): BuildLanguagesMapOutput;
143
+
144
+ type TrailingSlashPolicy = "preserve" | "always" | "never";
145
+ declare function normalizeUrl(url: string, trailingSlash: TrailingSlashPolicy): string;
146
+ declare function resolveAbsoluteUrl(input: string, baseUrl: string): string;
147
+
148
+ type WithHreflangOptions = {
149
+ baseUrl?: string;
150
+ trailingSlash?: "preserve" | "always" | "never";
151
+ ensureAbsolute?: boolean;
152
+ ensureXDefault?: boolean;
153
+ ensureSelf?: boolean;
154
+ canonicalLocale?: string;
155
+ xDefaultStrategy?: XDefaultStrategy;
156
+ shouldApply?: (entry: SitemapEntryLike) => boolean;
157
+ };
158
+ declare function withHreflang<T extends SitemapEntryLike>(entries: readonly T[], options: WithHreflangOptions): T[];
159
+ type AssertHreflangOptions = {
160
+ requireAbsolute?: boolean;
161
+ requireXDefaultWhenMultiple?: boolean;
162
+ requireSelf?: boolean;
163
+ canonicalLocale?: string;
164
+ };
165
+ declare function assertHreflangExport(entries: readonly SitemapEntryLike[], options: AssertHreflangOptions): HreflangReport;
166
+ /**
167
+ * Build hreflang entries using a routing strategy.
168
+ * This is the recommended way to use withHreflang with i18n routing.
169
+ */
170
+ declare function withHreflangFromRouting<T extends SitemapEntryLike>(entries: readonly T[], strategy: RoutingStrategy, options: {
171
+ baseUrl: string;
172
+ trailingSlash?: "preserve" | "always" | "never";
173
+ ensureAbsolute?: boolean;
174
+ ensureXDefault?: boolean;
175
+ ensureSelf?: boolean;
176
+ shouldApply?: (entry: SitemapEntryLike) => boolean;
177
+ }): T[];
178
+
179
+ /**
180
+ * Prefix-as-needed routing: default locale has no prefix, others have /locale
181
+ * Example: /about (en), /uk/about (uk), /de/about (de)
182
+ *
183
+ * Compatible with next-intl's prefix-as-needed strategy.
184
+ */
185
+ declare function routingPrefixAsNeeded(options: RoutingPrefixAsNeededOptions): RoutingStrategy;
186
+ /**
187
+ * Prefix-always routing: all locales have /locale prefix
188
+ * Example: /en/about, /uk/about, /de/about
189
+ *
190
+ * Compatible with next-intl's prefix-always strategy.
191
+ */
192
+ declare function routingPrefixAlways(options: RoutingPrefixAlwaysOptions): RoutingStrategy;
193
+ /**
194
+ * Domain-based routing: each locale has its own domain
195
+ * Example: example.com (en), example.de (de), example.ua (uk)
196
+ *
197
+ * Compatible with next-intl's domain-based routing.
198
+ */
199
+ declare function routingDomainBased(options: RoutingDomainBasedOptions): RoutingStrategy;
200
+ /**
201
+ * Suffix-locale routing: locale added as suffix to path
202
+ * Example: /blog (en), /blog/uk (uk), /blog/de (de)
203
+ *
204
+ * Common for blogs and content sections.
205
+ */
206
+ declare function routingSuffixLocale(options: RoutingSuffixLocaleOptions): RoutingStrategy;
207
+ /**
208
+ * Custom routing with user-defined function
209
+ */
210
+ declare function routingCustom(options: {
211
+ locales: readonly string[];
212
+ canonicalLocale: string;
213
+ hrefFor: (args: {
214
+ pathname: string;
215
+ locale: string;
216
+ }) => string;
217
+ xDefault?: RoutingStrategy["xDefault"];
218
+ }): RoutingStrategy;
219
+ /**
220
+ * PAS7 custom routing strategy:
221
+ * - Home: / (en), /uk, /de, /it, /hr
222
+ * - Hubs: /blog (en), /blog/uk, /blog/de
223
+ * - Details: /blog/en/<slug>, /blog/uk/<slug>
224
+ *
225
+ * This is a hybrid routing scheme where:
226
+ * - Home pages use prefix pattern for non-default locales
227
+ * - Hub pages (listing pages) use suffix pattern for non-default locales
228
+ * - Detail pages have locale as a segment after the section
229
+ */
230
+ declare function routingPAS7(options: RoutingPAS7Options): RoutingStrategy;
231
+
232
+ type ExpandLocalesOptions = {
233
+ mode: "cluster-only" | "expanded";
234
+ includeXDefault?: boolean;
235
+ locales?: readonly string[];
236
+ };
237
+ declare function expandLocaleEntries<T extends SitemapEntryLike>(entries: readonly T[], options: ExpandLocalesOptions): T[];
238
+
239
+ type InjectOptions = {
240
+ baseUrl?: string;
241
+ xDefaultStrategy?: XDefaultStrategy;
242
+ ensureNamespace?: boolean;
243
+ canonicalLocale?: string;
244
+ order?: "canonical-first" | "preserve";
245
+ trailingSlash?: "preserve" | "always" | "never";
246
+ };
247
+ declare function injectXDefaultIntoSitemapXml(xml: string, options: InjectOptions): string;
248
+
249
+ type CheckXmlOptions = {
250
+ requireNamespace?: boolean;
251
+ requireXDefaultWhenMultiple?: boolean;
252
+ requireAbsolute?: boolean;
253
+ checkDuplicateKeys?: boolean;
254
+ checkDuplicateHrefs?: boolean;
255
+ checkHreflangCasing?: boolean;
256
+ originPolicy?: "same" | "allowlist" | "off";
257
+ allowedOrigins?: string[];
258
+ };
259
+ declare function checkSitemapXmlHreflang(xml: string, options: CheckXmlOptions): HreflangReport;
260
+
261
+ export { type ChangeFrequency, type CheckXmlOptions, type CreateSitemapEntriesFromManifestOptions, type ExpandLocalesOptions, type HreflangIssue, type HreflangIssueCode, type HreflangReport, type InjectOptions, type LocalizedManifestItem, type ManifestRouteStyle, type RoutingDomainBasedOptions, type RoutingPAS7Options, type RoutingPrefixAlwaysOptions, type RoutingPrefixAsNeededOptions, type RoutingStrategy, type RoutingSuffixLocaleOptions, type SitemapAlternates, type SitemapEntry, type SitemapEntryLike, type XDefaultStrategy, assertHreflangExport as assertHreflang, buildLanguagesMap, checkSitemapXmlHreflang, createSitemapEntriesFromManifest, expandLocaleEntries, injectXDefaultIntoSitemapXml, normalizeUrl, resolveAbsoluteUrl, routingCustom, routingDomainBased, routingPAS7, routingPrefixAlways, routingPrefixAsNeeded, routingSuffixLocale, withHreflang, withHreflangFromRouting };