wpheadless-lib 1.1.10 → 1.1.12
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/api/categories.d.ts +1 -1
- package/dist/api/categories.js +18 -2
- package/dist/api/index.d.ts +7 -6
- package/dist/api/index.js +7 -6
- package/dist/api/mappers.d.ts +1 -1
- package/dist/api/mappers.js +1 -1
- package/dist/api/menus.d.ts +18 -0
- package/dist/api/menus.js +39 -0
- package/dist/api/posts.js +30 -2
- package/dist/api/translations.js +7 -1
- package/dist/api/wpClient.d.ts +5 -8
- package/dist/api/wpClient.js +14 -0
- package/dist/app/config.d.ts +2 -1
- package/dist/app/config.js +4 -0
- package/dist/app/globals.css +35 -124
- package/dist/base/category/index.d.ts +3 -3
- package/dist/base/category/index.js +9 -8
- package/dist/base/category/pagination.d.ts +2 -2
- package/dist/base/category/pagination.js +12 -10
- package/dist/base/home/index.js +1 -1
- package/dist/base/home/pagination.js +3 -3
- package/dist/base/index.d.ts +7 -7
- package/dist/base/index.js +7 -7
- package/dist/base/layout/RootLayoutBase.d.ts +7 -8
- package/dist/base/layout/RootLayoutBase.js +4 -4
- package/dist/base/layout/RootLayoutBase.module.css +10 -0
- package/dist/base/legal/index.d.ts +4 -4
- package/dist/base/legal/index.js +36 -24
- package/dist/base/post/index.d.ts +1 -1
- package/dist/base/post/index.js +15 -12
- package/dist/components/Breadcrumbs/index.d.ts +1 -1
- package/dist/components/Breadcrumbs/index.js +4 -4
- package/dist/components/JsonLd.d.ts +5 -0
- package/dist/components/JsonLd.js +9 -0
- package/dist/components/Paginator/index.d.ts +2 -2
- package/dist/components/Paginator/index.js +5 -5
- package/dist/components/PostCard/index.d.ts +3 -2
- package/dist/components/PostCard/index.js +8 -6
- package/dist/components/PostCard/index.module.css +7 -7
- package/dist/components/PostCard/index.types.d.ts +2 -1
- package/dist/components/PostCard/index.utils.d.ts +5 -5
- package/dist/components/PostCard/index.utils.js +8 -6
- package/dist/components/index.d.ts +6 -5
- package/dist/components/index.js +6 -5
- package/dist/components/layout/Footer/index.d.ts +6 -6
- package/dist/components/layout/Footer/index.js +11 -22
- package/dist/components/layout/Footer/index.module.css +59 -9
- package/dist/components/layout/Header/HeaderClient.d.ts +2 -2
- package/dist/components/layout/Header/HeaderClient.js +22 -2
- package/dist/components/layout/Header/index.d.ts +6 -6
- package/dist/components/layout/Header/index.js +10 -29
- package/dist/components/layout/Header/index.module.css +77 -16
- package/dist/components/ui/alert.d.ts +8 -0
- package/dist/components/ui/alert.js +12 -0
- package/dist/components/ui/alert.module.css +26 -0
- package/dist/components/ui/badge.d.ts +3 -0
- package/dist/components/ui/badge.js +9 -0
- package/dist/components/ui/badge.module.css +23 -0
- package/dist/components/ui/breadcrumb.d.ts +8 -0
- package/dist/components/ui/breadcrumb.js +22 -0
- package/dist/components/ui/breadcrumb.module.css +37 -0
- package/dist/components/ui/button.d.ts +7 -0
- package/dist/components/ui/button.js +16 -0
- package/dist/components/ui/button.module.css +72 -0
- package/dist/components/ui/card.d.ts +11 -0
- package/dist/components/ui/card.js +16 -0
- package/dist/components/ui/card.module.css +37 -0
- package/dist/components/ui/cn.d.ts +1 -0
- package/dist/components/ui/cn.js +3 -0
- package/dist/components/ui/index.d.ts +6 -0
- package/dist/components/ui/index.js +6 -0
- package/dist/components/ui/pagination.d.ts +14 -0
- package/dist/components/ui/pagination.js +25 -0
- package/dist/components/ui/pagination.module.css +62 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -6
- package/dist/plugins/index.d.ts +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/yoast/index.js +10 -7
- package/dist/utils/hreflang.d.ts +5 -7
- package/dist/utils/hreflang.js +19 -8
- package/dist/utils/html.d.ts +2 -0
- package/dist/utils/html.js +25 -0
- package/dist/utils/index.d.ts +7 -6
- package/dist/utils/index.js +7 -6
- package/dist/utils/language.d.ts +37 -0
- package/dist/utils/language.js +75 -0
- package/dist/utils/seo.d.ts +1 -6
- package/dist/utils/seo.js +9 -5
- package/dist/utils/sitemap.d.ts +1 -1
- package/dist/utils/sitemap.js +181 -63
- package/dist/views/CategoryListView/index.d.ts +2 -2
- package/dist/views/CategoryListView/index.js +6 -6
- package/dist/views/CategoryListView/index.utils.d.ts +1 -1
- package/dist/views/CategoryListView/index.utils.js +1 -1
- package/dist/views/CategoryPaginationView/index.d.ts +2 -2
- package/dist/views/CategoryPaginationView/index.js +6 -6
- package/dist/views/CategoryPaginationView/index.utils.d.ts +1 -1
- package/dist/views/CategoryPaginationView/index.utils.js +1 -1
- package/dist/views/HomePaginationView/index.d.ts +2 -2
- package/dist/views/HomePaginationView/index.js +5 -4
- package/dist/views/HomePaginationView/index.utils.d.ts +1 -1
- package/dist/views/HomePaginationView/index.utils.js +1 -1
- package/dist/views/HomeView/index.d.ts +2 -2
- package/dist/views/HomeView/index.js +13 -12
- package/dist/views/HomeView/index.module.css +51 -8
- package/dist/views/HomeView/index.utils.d.ts +1 -1
- package/dist/views/HomeView/index.utils.js +2 -2
- package/dist/views/LegalPageView/index.d.ts +2 -1
- package/dist/views/LegalPageView/index.js +5 -5
- package/dist/views/LegalPageView/index.module.css +3 -3
- package/dist/views/LegalPageView/index.utils.js +1 -1
- package/dist/views/PostView/index.d.ts +3 -2
- package/dist/views/PostView/index.js +9 -7
- package/dist/views/PostView/index.module.css +46 -13
- package/dist/views/PostView/index.utils.d.ts +3 -3
- package/dist/views/PostView/index.utils.js +2 -2
- package/dist/views/index.d.ts +6 -6
- package/dist/views/index.js +6 -6
- package/package.json +47 -10
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const normalizePath = (path) => {
|
|
2
|
+
if (!path || path === "/")
|
|
3
|
+
return "/";
|
|
4
|
+
const withLeadingSlash = path.startsWith("/") ? path : `/${path}`;
|
|
5
|
+
return withLeadingSlash.endsWith("/") ? withLeadingSlash : `${withLeadingSlash}/`;
|
|
6
|
+
};
|
|
7
|
+
const defaultSecondaryPath = (code) => normalizePath(code);
|
|
8
|
+
export function normalizeLanguages(languages, options = {}) {
|
|
9
|
+
const fallbackCode = options.defaultCode || options.defaultLocale || "en";
|
|
10
|
+
const source = languages && languages.length > 0
|
|
11
|
+
? languages
|
|
12
|
+
: [{ code: fallbackCode, locale: options.defaultLocale || fallbackCode }];
|
|
13
|
+
const explicitDefaultIndex = source.findIndex((language) => language.isDefault);
|
|
14
|
+
const defaultIndex = explicitDefaultIndex >= 0 ? explicitDefaultIndex : 0;
|
|
15
|
+
const isMulti = source.length > 1;
|
|
16
|
+
return source.map((language, index) => {
|
|
17
|
+
const isDefault = index === defaultIndex;
|
|
18
|
+
const code = language.code;
|
|
19
|
+
const basePath = language.basePath !== undefined
|
|
20
|
+
? normalizePath(language.basePath)
|
|
21
|
+
: isMulti && !isDefault
|
|
22
|
+
? defaultSecondaryPath(code)
|
|
23
|
+
: "/";
|
|
24
|
+
return {
|
|
25
|
+
...language,
|
|
26
|
+
code,
|
|
27
|
+
locale: language.locale || code,
|
|
28
|
+
basePath: isDefault ? "/" : basePath,
|
|
29
|
+
isDefault,
|
|
30
|
+
prefixed: isMulti && !isDefault,
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function getLanguageMode(languages) {
|
|
35
|
+
return normalizeLanguages(languages).length > 1 ? "multi" : "single";
|
|
36
|
+
}
|
|
37
|
+
export function getDefaultLanguage(languages) {
|
|
38
|
+
return normalizeLanguages(languages).find((language) => language.isDefault) ?? normalizeLanguages(languages)[0];
|
|
39
|
+
}
|
|
40
|
+
export function getLanguageByCode(languages, code) {
|
|
41
|
+
const normalized = normalizeLanguages(languages);
|
|
42
|
+
if (!code)
|
|
43
|
+
return normalized.find((language) => language.isDefault) ?? normalized[0];
|
|
44
|
+
return normalized.find((language) => language.code === code || language.locale === code);
|
|
45
|
+
}
|
|
46
|
+
export function getLanguageBasePath(language, allLanguages) {
|
|
47
|
+
if (allLanguages) {
|
|
48
|
+
const normalized = normalizeLanguages(allLanguages);
|
|
49
|
+
const match = normalized.find((item) => item.code === language.code) ??
|
|
50
|
+
normalized.find((item) => item.locale === language.locale);
|
|
51
|
+
if (match)
|
|
52
|
+
return match.basePath;
|
|
53
|
+
}
|
|
54
|
+
return normalizeLanguages([language])[0].basePath;
|
|
55
|
+
}
|
|
56
|
+
export function shouldRenderLanguageAlternates(languages) {
|
|
57
|
+
return normalizeLanguages(languages).length > 1;
|
|
58
|
+
}
|
|
59
|
+
export function buildLanguagePath(language, path = "", allLanguages) {
|
|
60
|
+
const basePath = getLanguageBasePath(language, allLanguages);
|
|
61
|
+
const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
|
|
62
|
+
return normalizePath(`${basePath}${normalizedPath}`);
|
|
63
|
+
}
|
|
64
|
+
export function getWpLanguageCode(language) {
|
|
65
|
+
return language?.wpLang;
|
|
66
|
+
}
|
|
67
|
+
export function getWpLanguageFilter(language) {
|
|
68
|
+
if (!language)
|
|
69
|
+
return {};
|
|
70
|
+
if (language.langId) {
|
|
71
|
+
return { taxonomies: { language: [language.langId] } };
|
|
72
|
+
}
|
|
73
|
+
const wpLang = getWpLanguageCode(language);
|
|
74
|
+
return wpLang ? { lang: wpLang } : {};
|
|
75
|
+
}
|
package/dist/utils/seo.d.ts
CHANGED
|
@@ -20,11 +20,6 @@ type FeaturedMedia = {
|
|
|
20
20
|
[key: string]: unknown;
|
|
21
21
|
};
|
|
22
22
|
type FeaturedMediaLike = Pick<FeaturedMedia, "source_url">;
|
|
23
|
-
type YoastSchemaHolder = {
|
|
24
|
-
yoast_head_json?: {
|
|
25
|
-
schema?: unknown;
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
23
|
type YoastHolder = {
|
|
29
24
|
yoast_head_json?: WPYoastHeadJson;
|
|
30
25
|
};
|
|
@@ -46,7 +41,7 @@ export declare function rewriteYoastUrls<T extends WPYoastHeadJson | undefined>(
|
|
|
46
41
|
export declare function getYoastHead(entity?: YoastHolder, opts?: RewriteOpts): WPYoastHeadJson | undefined;
|
|
47
42
|
export declare function buildYoastRobotsMeta(robots?: WPYoastHeadJson["robots"]): Metadata["robots"] | undefined;
|
|
48
43
|
export declare function isYoastNoindex(yoast?: WPYoastHeadJson): boolean;
|
|
49
|
-
export declare function getYoastSchema(entity?:
|
|
44
|
+
export declare function getYoastSchema(entity?: unknown, opts?: RewriteOpts): unknown;
|
|
50
45
|
export declare function stripBreadcrumbsFromSchema(schema: unknown): unknown;
|
|
51
46
|
export declare function getFeaturedMedia(entity?: WithEmbeddedMedia): FeaturedMedia | undefined;
|
|
52
47
|
export declare function getPlainTextExcerpt(html?: string, maxLength?: number): string | undefined;
|
package/dist/utils/seo.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { stripTags } from "./html";
|
|
1
|
+
import { stripTags, toPlainText } from "./html.js";
|
|
2
2
|
export function getOgImageUrl(entity, featuredMedia) {
|
|
3
3
|
const ogUrl = entity?.yoast_head_json?.og_image?.[0]?.url;
|
|
4
4
|
return ogUrl || featuredMedia?.source_url;
|
|
@@ -196,10 +196,14 @@ export function getFeaturedMedia(entity) {
|
|
|
196
196
|
return entity?._embedded?.["wp:featuredmedia"]?.[0];
|
|
197
197
|
}
|
|
198
198
|
export function getPlainTextExcerpt(html, maxLength = 160) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
const text = toPlainText(html);
|
|
200
|
+
if (!text || maxLength <= 0 || text.length <= maxLength)
|
|
201
|
+
return text;
|
|
202
|
+
const truncated = text.slice(0, maxLength).trimEnd();
|
|
203
|
+
const lastSpace = truncated.lastIndexOf(" ");
|
|
204
|
+
return lastSpace > maxLength * 0.6
|
|
205
|
+
? truncated.slice(0, lastSpace).trimEnd()
|
|
206
|
+
: truncated;
|
|
203
207
|
}
|
|
204
208
|
export function buildBreadcrumbSchema(items) {
|
|
205
209
|
return {
|
package/dist/utils/sitemap.d.ts
CHANGED
package/dist/utils/sitemap.js
CHANGED
|
@@ -1,28 +1,80 @@
|
|
|
1
1
|
import { createPageEndpoints, createPostsEndpoints } from "wpjsapi-lib";
|
|
2
|
-
import { createWpClient } from "../api/wpClient";
|
|
3
|
-
import { listPostsWithEmbeds } from "../api/posts";
|
|
4
|
-
import { getCategoryPaginationStaticParams } from "../base";
|
|
5
|
-
import { getHomePaginationStaticParams } from "../base/home/pagination";
|
|
6
|
-
import { getAbsoluteUrl, ensureTrailingSlash } from "./routing";
|
|
7
|
-
import { isYoastNoindex } from "./seo";
|
|
8
|
-
import { getTranslationKey, getEntityLanguageId, withXDefault, } from "./hreflang";
|
|
2
|
+
import { createWpClient, isValidWpApiUrl } from "../api/wpClient.js";
|
|
3
|
+
import { listPostsWithEmbeds } from "../api/posts.js";
|
|
4
|
+
import { getCategoryPaginationStaticParams, getCategoryTotalPages, } from "../base/index.js";
|
|
5
|
+
import { getHomePaginationStaticParams, getHomeTotalPages, } from "../base/home/pagination.js";
|
|
6
|
+
import { getAbsoluteUrl, ensureTrailingSlash } from "./routing.js";
|
|
7
|
+
import { isYoastNoindex } from "./seo.js";
|
|
8
|
+
import { getHreflangCode, getTranslationKey, getEntityLanguageId, withXDefault, } from "./hreflang.js";
|
|
9
|
+
import { normalizeLanguages, shouldRenderLanguageAlternates, } from "./language.js";
|
|
9
10
|
const resolveWpApiUrl = (cfg) => cfg.wpApiUrl ?? process.env.WP_API_URL ?? "";
|
|
10
11
|
const resolveSiteUrl = (cfg) => cfg.siteUrl ?? process.env.NEXT_PUBLIC_SITE_URL;
|
|
11
|
-
const buildHomeAlternates = (cfg) =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
const buildHomeAlternates = (cfg) => shouldRenderLanguageAlternates(cfg.languages)
|
|
13
|
+
? withXDefault(normalizeLanguages(cfg.languages).reduce((acc, langCfg) => {
|
|
14
|
+
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
15
|
+
acc[getHreflangCode(langCfg)] = getAbsoluteUrl(basePath, resolveSiteUrl(cfg));
|
|
16
|
+
return acc;
|
|
17
|
+
}, {}))
|
|
18
|
+
: undefined;
|
|
19
|
+
async function buildHomePaginationAlternates(cfg, currentPage) {
|
|
20
|
+
if (!shouldRenderLanguageAlternates(cfg.languages))
|
|
21
|
+
return undefined;
|
|
22
|
+
const wpApiUrl = resolveWpApiUrl(cfg);
|
|
23
|
+
if (!isValidWpApiUrl(wpApiUrl))
|
|
24
|
+
return undefined;
|
|
25
|
+
const siteUrl = resolveSiteUrl(cfg);
|
|
26
|
+
const alternates = {};
|
|
27
|
+
for (const langCfg of normalizeLanguages(cfg.languages)) {
|
|
28
|
+
const totalPages = await getHomeTotalPages({
|
|
29
|
+
baseApiUrl: wpApiUrl,
|
|
30
|
+
perPage: cfg.runtimeConfig.postsPerPagePagination,
|
|
31
|
+
langId: langCfg.langId,
|
|
32
|
+
});
|
|
33
|
+
if (totalPages < currentPage)
|
|
34
|
+
continue;
|
|
35
|
+
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
36
|
+
alternates[getHreflangCode(langCfg)] = getAbsoluteUrl(`${basePath}page/${currentPage}/`, siteUrl);
|
|
37
|
+
}
|
|
38
|
+
return withXDefault(alternates);
|
|
39
|
+
}
|
|
40
|
+
const escapeXml = (value) => value
|
|
41
|
+
.replace(/&/g, "&")
|
|
42
|
+
.replace(/</g, "<")
|
|
43
|
+
.replace(/>/g, ">")
|
|
44
|
+
.replace(/"/g, """)
|
|
45
|
+
.replace(/'/g, "'");
|
|
46
|
+
const renderAlternates = (alternates) => {
|
|
47
|
+
const normalizedAlternates = withXDefault(alternates);
|
|
48
|
+
if (!normalizedAlternates)
|
|
49
|
+
return undefined;
|
|
50
|
+
return Object.entries(normalizedAlternates)
|
|
51
|
+
.map(([code, href]) => `<xhtml:link rel="alternate" hreflang="${escapeXml(code)}" href="${escapeXml(href)}" />`)
|
|
52
|
+
.join("");
|
|
53
|
+
};
|
|
16
54
|
const getYoastHeadJson = (entity) => entity.yoast_head_json;
|
|
17
55
|
const isNoindexEntity = (entity) => isYoastNoindex(getYoastHeadJson(entity));
|
|
56
|
+
const getWpLangParam = (language) => {
|
|
57
|
+
const lang = language.wpLang || (language.langId ? language.code : undefined);
|
|
58
|
+
return lang ? { lang } : {};
|
|
59
|
+
};
|
|
60
|
+
async function mapConcurrent(items, mapper, concurrency = 5) {
|
|
61
|
+
const results = new Array(items.length);
|
|
62
|
+
let nextIndex = 0;
|
|
63
|
+
async function worker() {
|
|
64
|
+
while (nextIndex < items.length) {
|
|
65
|
+
const currentIndex = nextIndex;
|
|
66
|
+
nextIndex += 1;
|
|
67
|
+
results[currentIndex] = await mapper(items[currentIndex], currentIndex);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
|
|
71
|
+
return results;
|
|
72
|
+
}
|
|
18
73
|
export function renderSitemap(entries) {
|
|
19
74
|
const items = entries
|
|
20
75
|
.map((entry) => {
|
|
21
|
-
const links = entry.alternates
|
|
22
|
-
|
|
23
|
-
.map(([code, href]) => `<xhtml:link rel="alternate" hreflang="${code}" href="${href}" />`)
|
|
24
|
-
.join("");
|
|
25
|
-
return `<url><loc>${entry.url}</loc>${entry.lastmod ? `<lastmod>${entry.lastmod}</lastmod>` : ""}${links ?? ""}</url>`;
|
|
76
|
+
const links = renderAlternates(entry.alternates);
|
|
77
|
+
return `<url><loc>${escapeXml(entry.url)}</loc>${entry.lastmod ? `<lastmod>${escapeXml(entry.lastmod)}</lastmod>` : ""}${links ?? ""}</url>`;
|
|
26
78
|
})
|
|
27
79
|
.join("");
|
|
28
80
|
return (`<?xml version="1.0" encoding="UTF-8"?>` +
|
|
@@ -32,7 +84,7 @@ export function renderSitemap(entries) {
|
|
|
32
84
|
}
|
|
33
85
|
export function renderSitemapIndex(sitemaps) {
|
|
34
86
|
const items = sitemaps
|
|
35
|
-
.map((s) => `<sitemap><loc>${s.url}</loc>${s.lastmod ? `<lastmod>${s.lastmod}</lastmod>` : ""}</sitemap>`)
|
|
87
|
+
.map((s) => `<sitemap><loc>${escapeXml(s.url)}</loc>${s.lastmod ? `<lastmod>${escapeXml(s.lastmod)}</lastmod>` : ""}</sitemap>`)
|
|
36
88
|
.join("");
|
|
37
89
|
return (`<?xml version="1.0" encoding="UTF-8"?>` +
|
|
38
90
|
`<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
|
@@ -40,38 +92,42 @@ export function renderSitemapIndex(sitemaps) {
|
|
|
40
92
|
`</sitemapindex>`);
|
|
41
93
|
}
|
|
42
94
|
export async function getHomeEntries(cfg) {
|
|
43
|
-
const
|
|
44
|
-
const
|
|
95
|
+
const { runtimeConfig } = cfg;
|
|
96
|
+
const languages = normalizeLanguages(cfg.languages);
|
|
45
97
|
const wpApiUrl = resolveWpApiUrl(cfg);
|
|
46
98
|
const siteUrl = resolveSiteUrl(cfg);
|
|
47
99
|
const homeAlternates = buildHomeAlternates(cfg);
|
|
48
|
-
|
|
100
|
+
return mapConcurrent(languages, async (langCfg) => {
|
|
49
101
|
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
50
102
|
const homeUrl = getAbsoluteUrl(basePath, siteUrl);
|
|
51
|
-
const homePosts =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
103
|
+
const homePosts = isValidWpApiUrl(wpApiUrl)
|
|
104
|
+
? await listPostsWithEmbeds({
|
|
105
|
+
baseApiUrl: wpApiUrl,
|
|
106
|
+
perPage: runtimeConfig.postsPerPagePagination,
|
|
107
|
+
page: 1,
|
|
108
|
+
langId: langCfg.langId,
|
|
109
|
+
orderby: "date",
|
|
110
|
+
order: "desc",
|
|
111
|
+
})
|
|
112
|
+
: null;
|
|
113
|
+
const latest = homePosts?.ok ? homePosts.data?.items[0] : undefined;
|
|
60
114
|
const lastmod = latest?.modified ||
|
|
61
115
|
latest?.date;
|
|
62
|
-
|
|
116
|
+
return {
|
|
63
117
|
url: homeUrl,
|
|
64
118
|
lastmod: lastmod ? new Date(lastmod).toISOString() : undefined,
|
|
65
119
|
alternates: homeAlternates ?? undefined,
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return entries;
|
|
120
|
+
};
|
|
121
|
+
});
|
|
69
122
|
}
|
|
70
123
|
export async function getHomePaginationEntries(cfg) {
|
|
71
124
|
const entries = [];
|
|
72
|
-
const {
|
|
125
|
+
const { runtimeConfig } = cfg;
|
|
126
|
+
const languages = normalizeLanguages(cfg.languages);
|
|
73
127
|
const wpApiUrl = resolveWpApiUrl(cfg);
|
|
74
128
|
const siteUrl = resolveSiteUrl(cfg);
|
|
129
|
+
if (!isValidWpApiUrl(wpApiUrl))
|
|
130
|
+
return entries;
|
|
75
131
|
for (const langCfg of languages) {
|
|
76
132
|
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
77
133
|
const pages = await getHomePaginationStaticParams({
|
|
@@ -79,7 +135,7 @@ export async function getHomePaginationEntries(cfg) {
|
|
|
79
135
|
perPage: runtimeConfig.postsPerPagePagination,
|
|
80
136
|
langId: langCfg.langId,
|
|
81
137
|
});
|
|
82
|
-
|
|
138
|
+
const pageEntries = await mapConcurrent(pages, async (p) => {
|
|
83
139
|
const url = getAbsoluteUrl(`${basePath}page/${p.page}/`, siteUrl);
|
|
84
140
|
const pagePosts = await listPostsWithEmbeds({
|
|
85
141
|
baseApiUrl: wpApiUrl,
|
|
@@ -92,31 +148,39 @@ export async function getHomePaginationEntries(cfg) {
|
|
|
92
148
|
const latest = pagePosts.ok ? pagePosts.data?.items[0] : undefined;
|
|
93
149
|
const lastmod = latest?.modified ||
|
|
94
150
|
latest?.date;
|
|
95
|
-
|
|
151
|
+
return {
|
|
96
152
|
url,
|
|
97
153
|
lastmod: lastmod ? new Date(lastmod).toISOString() : undefined,
|
|
98
|
-
|
|
99
|
-
|
|
154
|
+
alternates: await buildHomePaginationAlternates(cfg, Number(p.page)),
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
entries.push(...pageEntries);
|
|
100
158
|
}
|
|
101
159
|
return entries;
|
|
102
160
|
}
|
|
103
161
|
export async function getCategoryEntries(cfg) {
|
|
104
162
|
const entries = [];
|
|
105
|
-
const {
|
|
163
|
+
const { runtimeConfig } = cfg;
|
|
164
|
+
const languages = normalizeLanguages(cfg.languages);
|
|
106
165
|
const wpApiUrl = resolveWpApiUrl(cfg);
|
|
107
166
|
const siteUrl = resolveSiteUrl(cfg);
|
|
167
|
+
if (!isValidWpApiUrl(wpApiUrl))
|
|
168
|
+
return entries;
|
|
169
|
+
const renderAlternatesForLanguages = shouldRenderLanguageAlternates(cfg.languages);
|
|
108
170
|
const categoriesPerLang = {};
|
|
109
171
|
const categoryAlternates = {};
|
|
110
172
|
for (const langCfg of languages) {
|
|
111
173
|
const { categoriesApi } = createWpClient({ baseUrl: wpApiUrl });
|
|
112
174
|
const categories = await categoriesApi.listAll({
|
|
113
|
-
...(langCfg
|
|
175
|
+
...getWpLangParam(langCfg),
|
|
114
176
|
_fields: ["id", "slug", "name", "description", "meta", "yoast_head_json"],
|
|
115
177
|
});
|
|
116
178
|
const indexableCategories = categories.filter((cat) => !isNoindexEntity(cat));
|
|
117
179
|
categoriesPerLang[langCfg.code] = indexableCategories;
|
|
118
180
|
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
119
181
|
for (const cat of indexableCategories) {
|
|
182
|
+
if (!renderAlternatesForLanguages)
|
|
183
|
+
continue;
|
|
120
184
|
const translationKey = getTranslationKey(cat);
|
|
121
185
|
if (!translationKey)
|
|
122
186
|
continue;
|
|
@@ -124,13 +188,13 @@ export async function getCategoryEntries(cfg) {
|
|
|
124
188
|
if (!categoryAlternates[translationKey]) {
|
|
125
189
|
categoryAlternates[translationKey] = {};
|
|
126
190
|
}
|
|
127
|
-
categoryAlternates[translationKey][langCfg
|
|
191
|
+
categoryAlternates[translationKey][getHreflangCode(langCfg)] = url;
|
|
128
192
|
}
|
|
129
193
|
}
|
|
130
194
|
for (const langCfg of languages) {
|
|
131
195
|
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
132
196
|
const categories = categoriesPerLang[langCfg.code] ?? [];
|
|
133
|
-
|
|
197
|
+
const categoryEntries = await mapConcurrent(categories, async (cat) => {
|
|
134
198
|
const url = getAbsoluteUrl(`${basePath}${cat.slug}/`, siteUrl);
|
|
135
199
|
const catPosts = await listPostsWithEmbeds({
|
|
136
200
|
baseApiUrl: wpApiUrl,
|
|
@@ -145,49 +209,84 @@ export async function getCategoryEntries(cfg) {
|
|
|
145
209
|
const lastmod = latest?.modified ||
|
|
146
210
|
latest?.date;
|
|
147
211
|
const alt = (() => {
|
|
212
|
+
if (!renderAlternatesForLanguages)
|
|
213
|
+
return undefined;
|
|
148
214
|
const key = getTranslationKey(cat);
|
|
149
215
|
if (!key)
|
|
150
216
|
return undefined;
|
|
151
217
|
const a = withXDefault(categoryAlternates[key]);
|
|
152
218
|
return a;
|
|
153
219
|
})();
|
|
154
|
-
|
|
220
|
+
return {
|
|
155
221
|
url,
|
|
156
222
|
lastmod: lastmod ? new Date(lastmod).toISOString() : undefined,
|
|
157
223
|
alternates: alt,
|
|
158
|
-
}
|
|
159
|
-
}
|
|
224
|
+
};
|
|
225
|
+
});
|
|
226
|
+
entries.push(...categoryEntries);
|
|
160
227
|
}
|
|
161
228
|
return entries;
|
|
162
229
|
}
|
|
163
230
|
export async function getCategoryPaginationEntries(cfg) {
|
|
164
231
|
const entries = [];
|
|
165
|
-
const {
|
|
232
|
+
const { runtimeConfig } = cfg;
|
|
233
|
+
const languages = normalizeLanguages(cfg.languages);
|
|
166
234
|
const wpApiUrl = resolveWpApiUrl(cfg);
|
|
167
235
|
const siteUrl = resolveSiteUrl(cfg);
|
|
236
|
+
if (!isValidWpApiUrl(wpApiUrl))
|
|
237
|
+
return entries;
|
|
238
|
+
const renderAlternatesForLanguages = shouldRenderLanguageAlternates(cfg.languages);
|
|
168
239
|
const catIdsBySlugByLang = {};
|
|
240
|
+
const catsBySlugByLang = {};
|
|
241
|
+
const alternatesByTranslationPage = {};
|
|
169
242
|
for (const langCfg of languages) {
|
|
170
243
|
const { categoriesApi } = createWpClient({ baseUrl: wpApiUrl });
|
|
171
244
|
const categories = await categoriesApi.listAll({
|
|
172
|
-
|
|
173
|
-
_fields: ["id", "slug", "yoast_head_json"],
|
|
245
|
+
...getWpLangParam(langCfg),
|
|
246
|
+
_fields: ["id", "slug", "meta", "yoast_head_json"],
|
|
174
247
|
});
|
|
175
248
|
const indexableCategories = categories.filter((cat) => !isNoindexEntity(cat));
|
|
176
249
|
catIdsBySlugByLang[langCfg.code] = Object.fromEntries(indexableCategories.map((c) => [c.slug, c.id]));
|
|
250
|
+
catsBySlugByLang[langCfg.code] = Object.fromEntries(indexableCategories.map((c) => [c.slug, c]));
|
|
251
|
+
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
252
|
+
for (const category of indexableCategories) {
|
|
253
|
+
if (!renderAlternatesForLanguages)
|
|
254
|
+
continue;
|
|
255
|
+
const translationKey = getTranslationKey(category);
|
|
256
|
+
if (!translationKey)
|
|
257
|
+
continue;
|
|
258
|
+
const totalPages = await getCategoryTotalPages({
|
|
259
|
+
baseApiUrl: wpApiUrl,
|
|
260
|
+
categoryId: category.id,
|
|
261
|
+
perPage: runtimeConfig.postsPerPagePagination,
|
|
262
|
+
langId: langCfg.langId,
|
|
263
|
+
});
|
|
264
|
+
for (let page = 2; page <= totalPages; page++) {
|
|
265
|
+
const pageKey = String(page);
|
|
266
|
+
if (!alternatesByTranslationPage[translationKey]) {
|
|
267
|
+
alternatesByTranslationPage[translationKey] = {};
|
|
268
|
+
}
|
|
269
|
+
if (!alternatesByTranslationPage[translationKey][pageKey]) {
|
|
270
|
+
alternatesByTranslationPage[translationKey][pageKey] = {};
|
|
271
|
+
}
|
|
272
|
+
alternatesByTranslationPage[translationKey][pageKey][getHreflangCode(langCfg)] = getAbsoluteUrl(`${basePath}${category.slug}/page/${page}/`, siteUrl);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
177
275
|
}
|
|
178
276
|
for (const langCfg of languages) {
|
|
179
277
|
const catPages = await getCategoryPaginationStaticParams({
|
|
180
278
|
baseApiUrl: wpApiUrl,
|
|
181
279
|
perPage: runtimeConfig.postsPerPagePagination,
|
|
182
|
-
lang: langCfg.code,
|
|
280
|
+
lang: langCfg.wpLang || (langCfg.langId ? langCfg.code : undefined) || "",
|
|
183
281
|
langId: langCfg.langId,
|
|
184
282
|
});
|
|
185
283
|
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
186
|
-
|
|
284
|
+
const pageEntries = await mapConcurrent(catPages, async (page) => {
|
|
187
285
|
const url = getAbsoluteUrl(`${basePath}${page.category}/page/${page.page}/`, siteUrl);
|
|
188
286
|
const catId = catIdsBySlugByLang[langCfg.code]?.[page.category];
|
|
189
287
|
if (!catId)
|
|
190
|
-
|
|
288
|
+
return null;
|
|
289
|
+
const category = catsBySlugByLang[langCfg.code]?.[page.category];
|
|
191
290
|
let lastmod;
|
|
192
291
|
const pagePosts = await listPostsWithEmbeds({
|
|
193
292
|
baseApiUrl: wpApiUrl,
|
|
@@ -202,22 +301,29 @@ export async function getCategoryPaginationEntries(cfg) {
|
|
|
202
301
|
lastmod =
|
|
203
302
|
latest?.modified ||
|
|
204
303
|
latest?.date;
|
|
205
|
-
|
|
304
|
+
return {
|
|
206
305
|
url,
|
|
207
306
|
lastmod: lastmod ? new Date(lastmod).toISOString() : undefined,
|
|
208
|
-
|
|
209
|
-
|
|
307
|
+
alternates: renderAlternatesForLanguages && category
|
|
308
|
+
? withXDefault(alternatesByTranslationPage[getTranslationKey(category) || ""]?.[page.page])
|
|
309
|
+
: undefined,
|
|
310
|
+
};
|
|
311
|
+
});
|
|
312
|
+
entries.push(...pageEntries.filter(Boolean));
|
|
210
313
|
}
|
|
211
314
|
return entries;
|
|
212
315
|
}
|
|
213
316
|
export async function getPostEntriesForLang(langCode, cfg) {
|
|
214
|
-
const
|
|
317
|
+
const languages = normalizeLanguages(cfg.languages);
|
|
215
318
|
const langCfg = languages.find((l) => l.code === langCode);
|
|
216
319
|
if (!langCfg)
|
|
217
320
|
return [];
|
|
218
321
|
const wpApiUrl = resolveWpApiUrl(cfg);
|
|
322
|
+
if (!isValidWpApiUrl(wpApiUrl))
|
|
323
|
+
return [];
|
|
219
324
|
const siteUrl = resolveSiteUrl(cfg);
|
|
220
325
|
const postsApi = createPostsEndpoints({ baseUrl: wpApiUrl });
|
|
326
|
+
const renderAlternatesForLanguages = shouldRenderLanguageAlternates(cfg.languages);
|
|
221
327
|
const languageFilter = langCfg.langId
|
|
222
328
|
? { taxonomies: { language: [langCfg.langId] } }
|
|
223
329
|
: {};
|
|
@@ -228,7 +334,7 @@ export async function getPostEntriesForLang(langCode, cfg) {
|
|
|
228
334
|
});
|
|
229
335
|
const indexablePosts = posts.filter((post) => !isNoindexEntity(post));
|
|
230
336
|
const postAlternates = {};
|
|
231
|
-
|
|
337
|
+
const postsByLanguage = await mapConcurrent(languages, async (l) => {
|
|
232
338
|
const base = ensureTrailingSlash(l.basePath || "/");
|
|
233
339
|
const langPosts = l.code === langCfg.code
|
|
234
340
|
? indexablePosts
|
|
@@ -240,7 +346,12 @@ export async function getPostEntriesForLang(langCode, cfg) {
|
|
|
240
346
|
const filteredLangPosts = l.code === langCfg.code
|
|
241
347
|
? langPosts
|
|
242
348
|
: langPosts.filter((post) => !isNoindexEntity(post));
|
|
349
|
+
return { language: l, base, posts: filteredLangPosts };
|
|
350
|
+
});
|
|
351
|
+
for (const { language: l, base, posts: filteredLangPosts } of postsByLanguage) {
|
|
243
352
|
for (const p of filteredLangPosts) {
|
|
353
|
+
if (!renderAlternatesForLanguages)
|
|
354
|
+
continue;
|
|
244
355
|
const translationKey = getTranslationKey(p);
|
|
245
356
|
if (!translationKey)
|
|
246
357
|
continue;
|
|
@@ -251,7 +362,7 @@ export async function getPostEntriesForLang(langCode, cfg) {
|
|
|
251
362
|
const url = getAbsoluteUrl(`${base}${categorySlug}/${p.slug}/`, siteUrl);
|
|
252
363
|
if (!postAlternates[translationKey])
|
|
253
364
|
postAlternates[translationKey] = {};
|
|
254
|
-
postAlternates[translationKey][l
|
|
365
|
+
postAlternates[translationKey][getHreflangCode(l)] = url;
|
|
255
366
|
}
|
|
256
367
|
}
|
|
257
368
|
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
@@ -265,7 +376,7 @@ export async function getPostEntriesForLang(langCode, cfg) {
|
|
|
265
376
|
const lastmod = p.modified ||
|
|
266
377
|
p.date;
|
|
267
378
|
const translationKey = getTranslationKey(p);
|
|
268
|
-
const alts = translationKey
|
|
379
|
+
const alts = renderAlternatesForLanguages && translationKey
|
|
269
380
|
? withXDefault(postAlternates[translationKey])
|
|
270
381
|
: undefined;
|
|
271
382
|
return {
|
|
@@ -278,9 +389,12 @@ export async function getPostEntriesForLang(langCode, cfg) {
|
|
|
278
389
|
}
|
|
279
390
|
export async function getLegalEntries(cfg) {
|
|
280
391
|
const entries = [];
|
|
281
|
-
const
|
|
392
|
+
const languages = normalizeLanguages(cfg.languages);
|
|
282
393
|
const siteUrl = resolveSiteUrl(cfg);
|
|
283
394
|
const wpApiUrl = resolveWpApiUrl(cfg);
|
|
395
|
+
if (!isValidWpApiUrl(wpApiUrl))
|
|
396
|
+
return entries;
|
|
397
|
+
const renderAlternatesForLanguages = shouldRenderLanguageAlternates(cfg.languages);
|
|
284
398
|
const pagesApi = createPageEndpoints({ baseUrl: wpApiUrl });
|
|
285
399
|
const pagesPerLang = {};
|
|
286
400
|
const alternatesByKey = {};
|
|
@@ -306,18 +420,22 @@ export async function getLegalEntries(cfg) {
|
|
|
306
420
|
"yoast_head_json",
|
|
307
421
|
],
|
|
308
422
|
});
|
|
309
|
-
const filtered =
|
|
423
|
+
const filtered = langCfg.langId
|
|
424
|
+
? pages.filter((p) => getEntityLanguageId(p)?.toString() === langCfg.langId?.toString())
|
|
425
|
+
: pages;
|
|
310
426
|
const indexablePages = filtered.filter((page) => !isNoindexEntity(page));
|
|
311
427
|
pagesPerLang[langCfg.code] = indexablePages;
|
|
312
428
|
const basePath = ensureTrailingSlash(langCfg.basePath || "/");
|
|
313
429
|
for (const p of indexablePages) {
|
|
430
|
+
if (!renderAlternatesForLanguages)
|
|
431
|
+
continue;
|
|
314
432
|
const translationKey = getTranslationKey(p);
|
|
315
433
|
if (!translationKey)
|
|
316
434
|
continue;
|
|
317
435
|
const url = getAbsoluteUrl(`${basePath}legal/${p.slug}/`, siteUrl);
|
|
318
436
|
if (!alternatesByKey[translationKey])
|
|
319
437
|
alternatesByKey[translationKey] = {};
|
|
320
|
-
alternatesByKey[translationKey][langCfg
|
|
438
|
+
alternatesByKey[translationKey][getHreflangCode(langCfg)] = url;
|
|
321
439
|
}
|
|
322
440
|
}
|
|
323
441
|
for (const langCfg of languages) {
|
|
@@ -327,7 +445,7 @@ export async function getLegalEntries(cfg) {
|
|
|
327
445
|
const url = getAbsoluteUrl(`${basePath}legal/${p.slug}/`, siteUrl);
|
|
328
446
|
const lastmod = p.modified || p.date;
|
|
329
447
|
const translationKey = getTranslationKey(p);
|
|
330
|
-
const alts = translationKey
|
|
448
|
+
const alts = renderAlternatesForLanguages && translationKey
|
|
331
449
|
? withXDefault(alternatesByKey[translationKey])
|
|
332
450
|
: undefined;
|
|
333
451
|
entries.push({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type WPCategory, type WPPost } from "wpjsapi-lib";
|
|
2
|
-
import { type Locale } from "../../utils";
|
|
2
|
+
import { type Locale } from "../../utils/index.js";
|
|
3
3
|
type CategoryListViewProps = {
|
|
4
4
|
category: WPCategory;
|
|
5
5
|
posts: WPPost[];
|
|
@@ -10,5 +10,5 @@ type CategoryListViewProps = {
|
|
|
10
10
|
locale?: Locale;
|
|
11
11
|
dateLocale?: string;
|
|
12
12
|
};
|
|
13
|
-
export declare function CategoryListView({ category, posts, totalPages, baseUrl, homeHref, linkBasePath, locale, dateLocale, }: CategoryListViewProps): import("react
|
|
13
|
+
export declare function CategoryListView({ category, posts, totalPages, baseUrl, homeHref, linkBasePath, locale, dateLocale, }: CategoryListViewProps): import("react").JSX.Element;
|
|
14
14
|
export {};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import Paginator from "../../components/Paginator";
|
|
3
|
-
import PostCard from "../../components/PostCard";
|
|
2
|
+
import Paginator from "../../components/Paginator/index.js";
|
|
3
|
+
import PostCard from "../../components/PostCard/index.js";
|
|
4
4
|
import styles from "./index.module.css";
|
|
5
|
-
import { getCountLabel, getEmptyLabel, getPaginatorBase } from "./index.utils";
|
|
6
|
-
import { Breadcrumbs } from "../../components";
|
|
7
|
-
import { getTranslator } from "../../utils";
|
|
5
|
+
import { getCountLabel, getEmptyLabel, getPaginatorBase } from "./index.utils.js";
|
|
6
|
+
import { Breadcrumbs, JsonLd } from "../../components/index.js";
|
|
7
|
+
import { getTranslator, getYoastSchema } from "../../utils/index.js";
|
|
8
8
|
export function CategoryListView({ category, posts, totalPages, baseUrl, homeHref = "/", linkBasePath, locale, dateLocale = "en-US", }) {
|
|
9
9
|
const paginatorBase = getPaginatorBase(category, baseUrl);
|
|
10
10
|
const countLabel = getCountLabel(category, locale);
|
|
11
11
|
const emptyLabel = getEmptyLabel(locale);
|
|
12
12
|
const t = getTranslator(locale);
|
|
13
|
-
return (_jsxs("div", { className:
|
|
13
|
+
return (_jsxs("div", { className: styles.container, children: [_jsx(JsonLd, { data: getYoastSchema(category) }), _jsxs("header", { className: styles.header, children: [_jsx(Breadcrumbs, { items: [
|
|
14
14
|
{ label: "Home", href: homeHref },
|
|
15
15
|
{ label: category.name },
|
|
16
16
|
] }), _jsx("h1", { className: styles.title, children: category.name }), category.description && (_jsx("div", { className: styles.description, dangerouslySetInnerHTML: { __html: category.description } })), countLabel && _jsx("p", { className: styles.count, children: countLabel })] }), posts.length === 0 ? (_jsx("p", { className: styles.empty, children: emptyLabel })) : (_jsxs("section", { "aria-label": t("home.title"), className: styles.gridSection, children: [_jsx("div", { className: styles.grid, children: posts.map((post) => (_jsx(PostCard, { post: post, categorySlug: category.slug, basePath: linkBasePath, locale: locale, dateLocale: dateLocale }, post.id))) }), _jsx(Paginator, { currentPage: 1, totalPages: totalPages, baseUrl: paginatorBase, locale: locale })] }))] }));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type WPCategory } from "wpjsapi-lib";
|
|
2
|
-
import { type Locale } from "../../utils";
|
|
2
|
+
import { type Locale } from "../../utils/index.js";
|
|
3
3
|
export declare const getPaginatorBase: (category: WPCategory, baseUrl?: string) => string;
|
|
4
4
|
export declare const getCountLabel: (category: WPCategory, locale?: Locale) => string | null;
|
|
5
5
|
export declare const getEmptyLabel: (locale?: Locale) => string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getTranslator } from "../../utils";
|
|
1
|
+
import { getTranslator } from "../../utils/index.js";
|
|
2
2
|
export const getPaginatorBase = (category, baseUrl) => baseUrl ?? `/${category.slug}`;
|
|
3
3
|
export const getCountLabel = (category, locale) => {
|
|
4
4
|
const t = getTranslator(locale);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type WPCategory, type WPPost } from "wpjsapi-lib";
|
|
2
|
-
import { type Locale } from "../../utils";
|
|
2
|
+
import { type Locale } from "../../utils/index.js";
|
|
3
3
|
type CategoryPaginationViewProps = {
|
|
4
4
|
category: WPCategory;
|
|
5
5
|
posts: WPPost[];
|
|
@@ -10,5 +10,5 @@ type CategoryPaginationViewProps = {
|
|
|
10
10
|
locale?: Locale;
|
|
11
11
|
dateLocale?: string;
|
|
12
12
|
};
|
|
13
|
-
export declare function CategoryPaginationView({ category, posts, currentPage, totalPages, baseUrl, linkBasePath, locale, dateLocale, }: CategoryPaginationViewProps): import("react
|
|
13
|
+
export declare function CategoryPaginationView({ category, posts, currentPage, totalPages, baseUrl, linkBasePath, locale, dateLocale, }: CategoryPaginationViewProps): import("react").JSX.Element;
|
|
14
14
|
export {};
|