@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.
- package/LICENSE +201 -0
- package/README.md +179 -0
- package/dist/cli.js +576 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +261 -0
- package/dist/index.js +783 -0
- package/dist/index.js.map +1 -0
- package/package.json +75 -0
package/dist/index.d.ts
ADDED
|
@@ -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 };
|