wpheadless-lib 1.0.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/api/categories.d.ts +29 -0
- package/dist/api/categories.js +91 -0
- package/dist/api/index.d.ts +6 -0
- package/dist/api/index.js +6 -0
- package/dist/api/mappers.d.ts +5 -0
- package/dist/api/mappers.js +30 -0
- package/dist/api/posts.d.ts +44 -0
- package/dist/api/posts.js +104 -0
- package/dist/api/translations.d.ts +16 -0
- package/dist/api/translations.js +28 -0
- package/dist/api/types.d.ts +30 -0
- package/dist/api/types.js +1 -0
- package/dist/api/wpClient.d.ts +31 -0
- package/dist/api/wpClient.js +23 -0
- package/dist/app/config.d.ts +5 -0
- package/dist/app/config.js +28 -0
- package/dist/app/globals.css +326 -0
- package/dist/base/category/index.d.ts +38 -0
- package/dist/base/category/index.js +104 -0
- package/dist/base/category/pagination.d.ts +44 -0
- package/dist/base/category/pagination.js +114 -0
- package/dist/base/home/index.d.ts +13 -0
- package/dist/base/home/index.js +20 -0
- package/dist/base/home/pagination.d.ts +36 -0
- package/dist/base/home/pagination.js +83 -0
- package/dist/base/index.d.ts +7 -0
- package/dist/base/index.js +7 -0
- package/dist/base/layout/RootLayoutBase.d.ts +22 -0
- package/dist/base/layout/RootLayoutBase.js +15 -0
- package/dist/base/legal/index.d.ts +31 -0
- package/dist/base/legal/index.js +167 -0
- package/dist/base/post/index.d.ts +31 -0
- package/dist/base/post/index.js +97 -0
- package/dist/components/Breadcrumbs/index.d.ts +9 -0
- package/dist/components/Breadcrumbs/index.js +11 -0
- package/dist/components/Breadcrumbs/index.module.css +39 -0
- package/dist/components/Paginator/index.d.ts +10 -0
- package/dist/components/Paginator/index.js +16 -0
- package/dist/components/Paginator/index.module.css +13 -0
- package/dist/components/Paginator/index.utils.d.ts +7 -0
- package/dist/components/Paginator/index.utils.js +19 -0
- package/dist/components/PostCard/index.d.ts +10 -0
- package/dist/components/PostCard/index.js +22 -0
- package/dist/components/PostCard/index.module.css +56 -0
- package/dist/components/PostCard/index.types.d.ts +7 -0
- package/dist/components/PostCard/index.types.js +1 -0
- package/dist/components/PostCard/index.utils.d.ts +8 -0
- package/dist/components/PostCard/index.utils.js +23 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.js +5 -0
- package/dist/components/layout/Footer/index.d.ts +12 -0
- package/dist/components/layout/Footer/index.js +36 -0
- package/dist/components/layout/Footer/index.module.css +61 -0
- package/dist/components/layout/Header/index.d.ts +13 -0
- package/dist/components/layout/Header/index.js +36 -0
- package/dist/components/layout/Header/index.module.css +48 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/index.js +1 -0
- package/dist/plugins/yoast/index.d.ts +16 -0
- package/dist/plugins/yoast/index.js +44 -0
- package/dist/utils/hreflang.d.ts +37 -0
- package/dist/utils/hreflang.js +95 -0
- package/dist/utils/html.d.ts +4 -0
- package/dist/utils/html.js +8 -0
- package/dist/utils/i18n.d.ts +12 -0
- package/dist/utils/i18n.js +161 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/routing.d.ts +40 -0
- package/dist/utils/routing.js +84 -0
- package/dist/utils/seo.d.ts +75 -0
- package/dist/utils/seo.js +97 -0
- package/dist/utils/sitemap.d.ts +26 -0
- package/dist/utils/sitemap.js +327 -0
- package/dist/views/CategoryListView/index.d.ts +12 -0
- package/dist/views/CategoryListView/index.js +17 -0
- package/dist/views/CategoryListView/index.module.css +39 -0
- package/dist/views/CategoryListView/index.utils.d.ts +5 -0
- package/dist/views/CategoryListView/index.utils.js +14 -0
- package/dist/views/CategoryPaginationView/index.d.ts +13 -0
- package/dist/views/CategoryPaginationView/index.js +18 -0
- package/dist/views/CategoryPaginationView/index.module.css +39 -0
- package/dist/views/CategoryPaginationView/index.utils.d.ts +5 -0
- package/dist/views/CategoryPaginationView/index.utils.js +4 -0
- package/dist/views/HomePaginationView/index.d.ts +13 -0
- package/dist/views/HomePaginationView/index.js +9 -0
- package/dist/views/HomePaginationView/index.module.css +38 -0
- package/dist/views/HomePaginationView/index.utils.d.ts +7 -0
- package/dist/views/HomePaginationView/index.utils.js +10 -0
- package/dist/views/HomeView/index.d.ts +13 -0
- package/dist/views/HomeView/index.js +21 -0
- package/dist/views/HomeView/index.module.css +78 -0
- package/dist/views/HomeView/index.utils.d.ts +23 -0
- package/dist/views/HomeView/index.utils.js +44 -0
- package/dist/views/LegalPageView/index.d.ts +8 -0
- package/dist/views/LegalPageView/index.js +12 -0
- package/dist/views/LegalPageView/index.module.css +39 -0
- package/dist/views/LegalPageView/index.utils.d.ts +11 -0
- package/dist/views/LegalPageView/index.utils.js +16 -0
- package/dist/views/PostView/index.d.ts +10 -0
- package/dist/views/PostView/index.js +26 -0
- package/dist/views/PostView/index.module.css +80 -0
- package/dist/views/PostView/index.types.d.ts +2 -0
- package/dist/views/PostView/index.types.js +1 -0
- package/dist/views/PostView/index.utils.d.ts +15 -0
- package/dist/views/PostView/index.utils.js +22 -0
- package/dist/views/index.d.ts +6 -0
- package/dist/views/index.js +6 -0
- package/package.json +45 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { getPlainTextExcerpt, getOgImageUrl, getFeaturedMedia, } from "../../utils";
|
|
2
|
+
import { withXDefault } from "../../utils/hreflang";
|
|
3
|
+
import { listPostsWithEmbeds, getPostsTotalPages } from "../../api/posts";
|
|
4
|
+
export async function getHomePaginationStaticParams({ baseApiUrl, perPage, langId, }) {
|
|
5
|
+
const totalPagesResult = await getPostsTotalPages({
|
|
6
|
+
baseApiUrl,
|
|
7
|
+
perPage,
|
|
8
|
+
langId,
|
|
9
|
+
});
|
|
10
|
+
if (!totalPagesResult.ok || totalPagesResult.data === null) {
|
|
11
|
+
if (totalPagesResult.error) {
|
|
12
|
+
console.error("Error generando rutas estáticas de paginación:", totalPagesResult.error);
|
|
13
|
+
}
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
return Array.from({ length: Math.max(totalPagesResult.data - 1, 0) }, (_, i) => ({
|
|
17
|
+
page: String(i + 2),
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
export async function getHomeTotalPages({ baseApiUrl, perPage, langId, }) {
|
|
21
|
+
const result = await getPostsTotalPages({
|
|
22
|
+
baseApiUrl,
|
|
23
|
+
perPage,
|
|
24
|
+
langId,
|
|
25
|
+
});
|
|
26
|
+
if (!result.ok || result.data === null) {
|
|
27
|
+
if (result.error) {
|
|
28
|
+
console.error("Error obteniendo total de páginas de home:", result.error);
|
|
29
|
+
}
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
return result.data;
|
|
33
|
+
}
|
|
34
|
+
export async function fetchHomePaginatedPosts({ baseApiUrl, perPage, page, langId, }) {
|
|
35
|
+
const postsResponse = await listPostsWithEmbeds({
|
|
36
|
+
perPage,
|
|
37
|
+
page,
|
|
38
|
+
baseApiUrl,
|
|
39
|
+
orderby: "date",
|
|
40
|
+
order: "desc",
|
|
41
|
+
langId,
|
|
42
|
+
});
|
|
43
|
+
if (!postsResponse.ok || !postsResponse.data) {
|
|
44
|
+
const error = postsResponse.error || "Error desconocido";
|
|
45
|
+
console.error("Error obteniendo posts:", error);
|
|
46
|
+
return { posts: [], totalPages: 0, error };
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
posts: postsResponse.data.items,
|
|
50
|
+
totalPages: postsResponse.data.pagination.totalPages,
|
|
51
|
+
error: null,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function buildHomePaginationMetadata({ translator, currentPage, canonicalBase, posts, siteName, languages, }) {
|
|
55
|
+
const canonical = `${canonicalBase.replace(/\/+$/, "")}/page/${currentPage}/`;
|
|
56
|
+
const fallbackDescription = getPlainTextExcerpt(posts[0]?.excerpt?.rendered, 160) ||
|
|
57
|
+
translator("site.paginationDescription");
|
|
58
|
+
const featuredMedia = getFeaturedMedia(posts[0]);
|
|
59
|
+
const imageUrl = getOgImageUrl(posts[0], featuredMedia);
|
|
60
|
+
const languageAlternates = withXDefault(languages);
|
|
61
|
+
return {
|
|
62
|
+
title: translator("site.paginationTitle"),
|
|
63
|
+
description: fallbackDescription,
|
|
64
|
+
alternates: {
|
|
65
|
+
canonical,
|
|
66
|
+
...(languageAlternates ? { languages: languageAlternates } : {}),
|
|
67
|
+
},
|
|
68
|
+
openGraph: {
|
|
69
|
+
title: translator("site.paginationTitle"),
|
|
70
|
+
description: fallbackDescription,
|
|
71
|
+
url: canonical,
|
|
72
|
+
siteName,
|
|
73
|
+
type: "website",
|
|
74
|
+
images: imageUrl ? [{ url: imageUrl }] : [],
|
|
75
|
+
},
|
|
76
|
+
twitter: {
|
|
77
|
+
card: "summary_large_image",
|
|
78
|
+
title: translator("site.paginationTitle"),
|
|
79
|
+
description: fallbackDescription,
|
|
80
|
+
images: imageUrl ? [imageUrl] : undefined,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import "../../app/globals.css";
|
|
3
|
+
export declare const fontClassName = "";
|
|
4
|
+
export declare const viewport: {
|
|
5
|
+
width: string;
|
|
6
|
+
initialScale: number;
|
|
7
|
+
maximumScale: number;
|
|
8
|
+
themeColor: string;
|
|
9
|
+
};
|
|
10
|
+
type RootLayoutBaseProps = {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
menuHeaderId: string;
|
|
13
|
+
menuFooterId: string;
|
|
14
|
+
siteName: string;
|
|
15
|
+
wpApiUrl: string;
|
|
16
|
+
wpUsername: string;
|
|
17
|
+
wpAppPassword: string;
|
|
18
|
+
homeHref?: string;
|
|
19
|
+
locale?: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function RootLayoutBase({ children, menuHeaderId, menuFooterId, siteName, wpApiUrl, wpUsername, wpAppPassword, homeHref, locale, }: RootLayoutBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "../../app/globals.css";
|
|
3
|
+
import Header from "../../components/layout/Header";
|
|
4
|
+
import Footer from "../../components/layout/Footer";
|
|
5
|
+
// Use system fonts to avoid external downloads during build.
|
|
6
|
+
export const fontClassName = "";
|
|
7
|
+
export const viewport = {
|
|
8
|
+
width: "device-width",
|
|
9
|
+
initialScale: 1,
|
|
10
|
+
maximumScale: 5,
|
|
11
|
+
themeColor: "#333333",
|
|
12
|
+
};
|
|
13
|
+
export function RootLayoutBase({ children, menuHeaderId, menuFooterId, siteName, wpApiUrl, wpUsername, wpAppPassword, homeHref, locale, }) {
|
|
14
|
+
return (_jsxs(_Fragment, { children: [_jsx(Header, { menuId: menuHeaderId, wpApiUrl: wpApiUrl, wpUsername: wpUsername, wpAppPassword: wpAppPassword, siteName: siteName, homeHref: homeHref, locale: locale }), _jsx("main", { id: "main-content", style: { minHeight: "calc(100vh - 200px)" }, children: children }), _jsx(Footer, { menuId: menuFooterId, wpApiUrl: wpApiUrl, wpUsername: wpUsername, wpAppPassword: wpAppPassword, siteName: siteName, locale: locale })] }));
|
|
15
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type WPPage } from "wpjsapi-lib";
|
|
2
|
+
import type { Metadata } from "next";
|
|
3
|
+
import { LanguageConfig } from "../../utils/hreflang";
|
|
4
|
+
type StaticParams = Array<{
|
|
5
|
+
slug: string;
|
|
6
|
+
}>;
|
|
7
|
+
export declare function getLegalStaticParams(baseApiUrl: string, lang: string, langId?: string): Promise<StaticParams>;
|
|
8
|
+
export declare function fetchLegalPage(baseApiUrl: string, slug: string, lang: string, langId?: string): Promise<WPPage | null>;
|
|
9
|
+
export declare function fetchPagesByTranslateKey({ baseApiUrl, translationKey, lang, langId, }: {
|
|
10
|
+
baseApiUrl: string;
|
|
11
|
+
translationKey: string;
|
|
12
|
+
lang: string;
|
|
13
|
+
langId?: string;
|
|
14
|
+
}): Promise<WPPage[]>;
|
|
15
|
+
export declare function buildLegalMetadata({ page, slug, canonicalBase, useYoast, siteName, languages, siteUrl, wpApiUrl, }: {
|
|
16
|
+
page: WPPage;
|
|
17
|
+
slug: string;
|
|
18
|
+
canonicalBase: string;
|
|
19
|
+
useYoast?: boolean;
|
|
20
|
+
siteName?: string;
|
|
21
|
+
languages?: Record<string, string>;
|
|
22
|
+
siteUrl?: string;
|
|
23
|
+
wpApiUrl?: string;
|
|
24
|
+
}): Metadata;
|
|
25
|
+
export declare function buildLegalLanguageAlternates({ page, languages, siteUrl, baseApiUrl, }: {
|
|
26
|
+
page: WPPage;
|
|
27
|
+
languages: LanguageConfig[];
|
|
28
|
+
siteUrl?: string;
|
|
29
|
+
baseApiUrl: string;
|
|
30
|
+
}): Promise<Record<string, string> | undefined>;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { createPageEndpoints } from "wpjsapi-lib";
|
|
2
|
+
import { getAbsoluteUrl, getFeaturedMedia, getPlainTextExcerpt, getYoastHead, } from "../../utils";
|
|
3
|
+
import { buildLanguageAlternatesPerLanguage, buildAbsoluteLangUrl, getEntityLanguageId, withXDefault, } from "../../utils/hreflang";
|
|
4
|
+
import { mapPageEntity } from "../../api/mappers";
|
|
5
|
+
async function getLegalParentId(baseApiUrl, lang, langId) {
|
|
6
|
+
const pagesApi = createPageEndpoints({ baseUrl: baseApiUrl });
|
|
7
|
+
try {
|
|
8
|
+
const parent = await pagesApi.list({
|
|
9
|
+
slug: "legal",
|
|
10
|
+
per_page: 1,
|
|
11
|
+
_fields: ["id", "language", "taxonomies", "meta"],
|
|
12
|
+
});
|
|
13
|
+
const match = parent.items.find((p) => langId && getEntityLanguageId(p)?.toString() === langId.toString());
|
|
14
|
+
return (match ?? parent.items[0])?.id ?? null;
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
console.error("Error obteniendo página padre legal:", error);
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function getLegalStaticParams(baseApiUrl, lang, langId) {
|
|
22
|
+
const pagesApi = createPageEndpoints({
|
|
23
|
+
baseUrl: baseApiUrl,
|
|
24
|
+
});
|
|
25
|
+
try {
|
|
26
|
+
const parentId = await getLegalParentId(baseApiUrl, lang, langId);
|
|
27
|
+
if (!parentId)
|
|
28
|
+
return [];
|
|
29
|
+
const pages = await pagesApi.listAll({
|
|
30
|
+
parent: parentId,
|
|
31
|
+
lang,
|
|
32
|
+
_fields: ["slug"],
|
|
33
|
+
});
|
|
34
|
+
return pages.map((page) => ({
|
|
35
|
+
slug: page.slug,
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error("Error generando rutas estáticas de páginas:", error);
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export async function fetchLegalPage(baseApiUrl, slug, lang, langId) {
|
|
44
|
+
const pagesApi = createPageEndpoints({
|
|
45
|
+
baseUrl: baseApiUrl,
|
|
46
|
+
});
|
|
47
|
+
try {
|
|
48
|
+
const parentId = await getLegalParentId(baseApiUrl, lang, langId);
|
|
49
|
+
if (!parentId)
|
|
50
|
+
return null;
|
|
51
|
+
const response = await pagesApi.list({
|
|
52
|
+
slug: slug,
|
|
53
|
+
per_page: 1,
|
|
54
|
+
_embed: true,
|
|
55
|
+
parent: parentId,
|
|
56
|
+
lang,
|
|
57
|
+
});
|
|
58
|
+
if (response.items.length === 0) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return response.items[0];
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
console.error("Error obteniendo página legal:", error);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export async function fetchPagesByTranslateKey({ baseApiUrl, translationKey, lang, langId, }) {
|
|
69
|
+
const pagesApi = createPageEndpoints({
|
|
70
|
+
baseUrl: baseApiUrl,
|
|
71
|
+
});
|
|
72
|
+
try {
|
|
73
|
+
const parentId = await getLegalParentId(baseApiUrl, lang, langId);
|
|
74
|
+
if (!parentId)
|
|
75
|
+
return [];
|
|
76
|
+
const response = await pagesApi.list({
|
|
77
|
+
per_page: 20,
|
|
78
|
+
_embed: true,
|
|
79
|
+
translation_key_v2: translationKey,
|
|
80
|
+
parent: parentId,
|
|
81
|
+
lang,
|
|
82
|
+
});
|
|
83
|
+
return response.items;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error("Error obteniendo traducciones de páginas:", error);
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export function buildLegalMetadata({ page, slug, canonicalBase, useYoast = true, siteName, languages, siteUrl, wpApiUrl, }) {
|
|
91
|
+
const url = getAbsoluteUrl(`${canonicalBase}legal/${slug}`, siteUrl);
|
|
92
|
+
const featuredMedia = getFeaturedMedia(page);
|
|
93
|
+
const fallbackDescription = getPlainTextExcerpt(page.excerpt.rendered, 160);
|
|
94
|
+
const imageUrl = featuredMedia?.source_url;
|
|
95
|
+
const languageAlternates = withXDefault(languages);
|
|
96
|
+
const baseMetadata = {
|
|
97
|
+
title: page.title.rendered,
|
|
98
|
+
description: fallbackDescription,
|
|
99
|
+
alternates: {
|
|
100
|
+
canonical: url,
|
|
101
|
+
...(languageAlternates ? { languages: languageAlternates } : {}),
|
|
102
|
+
},
|
|
103
|
+
openGraph: {
|
|
104
|
+
title: page.title.rendered,
|
|
105
|
+
description: fallbackDescription,
|
|
106
|
+
url,
|
|
107
|
+
siteName,
|
|
108
|
+
type: "website",
|
|
109
|
+
images: imageUrl ? [{ url: imageUrl }] : [],
|
|
110
|
+
},
|
|
111
|
+
twitter: {
|
|
112
|
+
card: "summary_large_image",
|
|
113
|
+
title: page.title.rendered,
|
|
114
|
+
description: fallbackDescription,
|
|
115
|
+
images: imageUrl ? [imageUrl] : undefined,
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
if (!useYoast)
|
|
119
|
+
return baseMetadata;
|
|
120
|
+
const yoast = getYoastHead(page, { siteUrl, wpApiUrl });
|
|
121
|
+
const yoastImageUrl = yoast?.og_image?.[0]?.url || imageUrl;
|
|
122
|
+
return {
|
|
123
|
+
title: yoast?.title || page.title.rendered,
|
|
124
|
+
description: yoast?.description || fallbackDescription,
|
|
125
|
+
alternates: {
|
|
126
|
+
canonical: url,
|
|
127
|
+
...(languageAlternates ? { languages: languageAlternates } : {}),
|
|
128
|
+
},
|
|
129
|
+
openGraph: {
|
|
130
|
+
title: yoast?.og_title || yoast?.title || page.title.rendered,
|
|
131
|
+
description: yoast?.og_description || yoast?.description || fallbackDescription,
|
|
132
|
+
url,
|
|
133
|
+
siteName: yoast?.og_site_name,
|
|
134
|
+
type: yoast?.og_type || "website",
|
|
135
|
+
images: yoastImageUrl ? [{ url: yoastImageUrl }] : [],
|
|
136
|
+
},
|
|
137
|
+
twitter: {
|
|
138
|
+
card: yoast?.twitter_card || "summary_large_image",
|
|
139
|
+
title: yoast?.twitter_title || yoast?.title || page.title.rendered,
|
|
140
|
+
description: yoast?.twitter_description || yoast?.description || fallbackDescription,
|
|
141
|
+
images: yoastImageUrl ? [yoastImageUrl] : undefined,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export async function buildLegalLanguageAlternates({ page, languages, siteUrl, baseApiUrl, }) {
|
|
146
|
+
const mappedPage = mapPageEntity(page);
|
|
147
|
+
const translationKey = mappedPage.meta.translationKey;
|
|
148
|
+
if (!translationKey)
|
|
149
|
+
return undefined;
|
|
150
|
+
return buildLanguageAlternatesPerLanguage({
|
|
151
|
+
languages,
|
|
152
|
+
fetcher: async (langCfg) => {
|
|
153
|
+
const pages = await fetchPagesByTranslateKey({
|
|
154
|
+
baseApiUrl,
|
|
155
|
+
translationKey,
|
|
156
|
+
lang: langCfg.code,
|
|
157
|
+
langId: langCfg.langId,
|
|
158
|
+
});
|
|
159
|
+
return (pages.find((p) => getEntityLanguageId(p)?.toString() === langCfg.langId?.toString()) || null);
|
|
160
|
+
},
|
|
161
|
+
buildUrl: ({ entity, langCfg }) => buildAbsoluteLangUrl({
|
|
162
|
+
basePath: langCfg.basePath,
|
|
163
|
+
path: `legal/${entity.slug}`,
|
|
164
|
+
siteUrl,
|
|
165
|
+
}),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type WPPost } from "wpjsapi-lib";
|
|
2
|
+
import type { Metadata } from "next";
|
|
3
|
+
type PostStaticParamsInput = {
|
|
4
|
+
baseApiUrl: string;
|
|
5
|
+
lang: string;
|
|
6
|
+
langId: string;
|
|
7
|
+
};
|
|
8
|
+
type PostStaticParam = {
|
|
9
|
+
category: string;
|
|
10
|
+
post: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function getPostStaticParams({ baseApiUrl, lang, langId, }: PostStaticParamsInput): Promise<PostStaticParam[]>;
|
|
13
|
+
export declare function fetchPostBySlug({ baseApiUrl, slug, langId, }: {
|
|
14
|
+
baseApiUrl: string;
|
|
15
|
+
slug: string;
|
|
16
|
+
langId: string;
|
|
17
|
+
}): Promise<WPPost | null>;
|
|
18
|
+
export declare function fetchPostsByTranslateKey({ baseApiUrl, translationKey, }: {
|
|
19
|
+
baseApiUrl: string;
|
|
20
|
+
translationKey: string;
|
|
21
|
+
}): Promise<WPPost[]>;
|
|
22
|
+
export declare function buildPostMetadata({ post, canonical, useYoast, siteName, languages, siteUrl, wpApiUrl, }: {
|
|
23
|
+
post: WPPost;
|
|
24
|
+
canonical: string;
|
|
25
|
+
useYoast?: boolean;
|
|
26
|
+
siteName?: string;
|
|
27
|
+
languages?: Record<string, string>;
|
|
28
|
+
siteUrl?: string;
|
|
29
|
+
wpApiUrl?: string;
|
|
30
|
+
}): Metadata;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { getFeaturedMedia, getOgImageUrl, getPlainTextExcerpt, getYoastHead, } from "../../utils";
|
|
2
|
+
import { getPostBySlug as getPostBySlugApi, listPostStaticParams, listPostsByTranslationKey, } from "../../api/posts";
|
|
3
|
+
import { withXDefault } from "../../utils/hreflang";
|
|
4
|
+
export async function getPostStaticParams({ baseApiUrl, lang, langId, }) {
|
|
5
|
+
const result = await listPostStaticParams({
|
|
6
|
+
baseApiUrl,
|
|
7
|
+
lang,
|
|
8
|
+
langId,
|
|
9
|
+
});
|
|
10
|
+
if (!result.ok || !result.data) {
|
|
11
|
+
if (result.error) {
|
|
12
|
+
console.error("Error generando rutas estáticas de posts:", result.error);
|
|
13
|
+
}
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
return result.data;
|
|
17
|
+
}
|
|
18
|
+
export async function fetchPostBySlug({ baseApiUrl, slug, langId, }) {
|
|
19
|
+
const result = await getPostBySlugApi({
|
|
20
|
+
baseApiUrl,
|
|
21
|
+
slug,
|
|
22
|
+
langId,
|
|
23
|
+
});
|
|
24
|
+
if (!result.ok) {
|
|
25
|
+
if (result.error)
|
|
26
|
+
console.error("Error obteniendo post:", result.error);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return result.data;
|
|
30
|
+
}
|
|
31
|
+
export async function fetchPostsByTranslateKey({ baseApiUrl, translationKey, }) {
|
|
32
|
+
const result = await listPostsByTranslationKey({
|
|
33
|
+
baseApiUrl,
|
|
34
|
+
translationKey,
|
|
35
|
+
});
|
|
36
|
+
if (!result.ok || !result.data) {
|
|
37
|
+
if (result.error)
|
|
38
|
+
console.error("Error obteniendo traducciones de post:", result.error);
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
return result.data;
|
|
42
|
+
}
|
|
43
|
+
export function buildPostMetadata({ post, canonical, useYoast = true, siteName, languages, siteUrl, wpApiUrl, }) {
|
|
44
|
+
const featuredMedia = getFeaturedMedia(post);
|
|
45
|
+
const imageUrl = getOgImageUrl(post, featuredMedia);
|
|
46
|
+
const fallbackDescription = getPlainTextExcerpt(post.excerpt?.rendered, 160);
|
|
47
|
+
const languageAlternates = withXDefault(languages);
|
|
48
|
+
const fallbackMeta = {
|
|
49
|
+
title: post.title.rendered,
|
|
50
|
+
description: fallbackDescription,
|
|
51
|
+
alternates: {
|
|
52
|
+
canonical,
|
|
53
|
+
...(languageAlternates ? { languages: languageAlternates } : {}),
|
|
54
|
+
},
|
|
55
|
+
openGraph: {
|
|
56
|
+
title: post.title.rendered,
|
|
57
|
+
description: fallbackDescription,
|
|
58
|
+
url: canonical,
|
|
59
|
+
type: "article",
|
|
60
|
+
siteName,
|
|
61
|
+
images: imageUrl ? [{ url: imageUrl }] : [],
|
|
62
|
+
},
|
|
63
|
+
twitter: {
|
|
64
|
+
card: "summary_large_image",
|
|
65
|
+
title: post.title.rendered,
|
|
66
|
+
description: fallbackDescription,
|
|
67
|
+
images: imageUrl ? [imageUrl] : undefined,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
if (!useYoast)
|
|
71
|
+
return fallbackMeta;
|
|
72
|
+
const yoast = getYoastHead(post, { siteUrl, wpApiUrl });
|
|
73
|
+
if (!yoast)
|
|
74
|
+
return fallbackMeta;
|
|
75
|
+
return {
|
|
76
|
+
title: yoast.title || post.title.rendered,
|
|
77
|
+
description: yoast.description || fallbackDescription,
|
|
78
|
+
alternates: {
|
|
79
|
+
canonical,
|
|
80
|
+
...(languageAlternates ? { languages: languageAlternates } : {}),
|
|
81
|
+
},
|
|
82
|
+
openGraph: {
|
|
83
|
+
title: yoast.og_title || yoast.title || post.title.rendered,
|
|
84
|
+
description: yoast.og_description || yoast.description || fallbackDescription,
|
|
85
|
+
url: canonical,
|
|
86
|
+
type: yoast.og_type || "article",
|
|
87
|
+
siteName: yoast.og_site_name,
|
|
88
|
+
images: imageUrl ? [{ url: imageUrl }] : [],
|
|
89
|
+
},
|
|
90
|
+
twitter: {
|
|
91
|
+
card: yoast.twitter_card || "summary_large_image",
|
|
92
|
+
title: yoast.twitter_title || yoast.title || post.title.rendered,
|
|
93
|
+
description: yoast.twitter_description || yoast.description || fallbackDescription,
|
|
94
|
+
images: imageUrl ? [imageUrl] : undefined,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Link from "next/link";
|
|
3
|
+
import styles from "./index.module.css";
|
|
4
|
+
export function Breadcrumbs({ items }) {
|
|
5
|
+
if (!items.length)
|
|
6
|
+
return null;
|
|
7
|
+
return (_jsx("nav", { "aria-label": "Breadcrumb", className: styles.nav, children: _jsx("ol", { className: styles.list, children: items.map((item, idx) => {
|
|
8
|
+
const isLast = idx === items.length - 1;
|
|
9
|
+
return (_jsxs("li", { className: styles.item, children: [item.href && !isLast ? (_jsx(Link, { href: item.href, className: styles.link, children: item.label })) : (_jsx("span", { className: styles.current, "aria-current": isLast ? "page" : undefined, children: item.label })), idx < items.length - 1 && (_jsx("span", { className: styles.separator, children: "/" }))] }, `${item.label}-${idx}`));
|
|
10
|
+
}) }) }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.nav {
|
|
2
|
+
margin-bottom: var(--spacing-md);
|
|
3
|
+
font-size: 0.95rem;
|
|
4
|
+
color: var(--foreground-light);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.list {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-wrap: wrap;
|
|
10
|
+
gap: 0.35rem;
|
|
11
|
+
list-style: none;
|
|
12
|
+
padding: 0;
|
|
13
|
+
margin: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.item {
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
gap: 0.35rem;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.link {
|
|
23
|
+
color: var(--foreground);
|
|
24
|
+
text-decoration: none;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.link:hover {
|
|
28
|
+
text-decoration: underline;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.current {
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
color: var(--foreground);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.separator {
|
|
37
|
+
color: var(--foreground-light);
|
|
38
|
+
}
|
|
39
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Locale } from "../../utils";
|
|
2
|
+
interface PaginatorProps {
|
|
3
|
+
currentPage: number;
|
|
4
|
+
totalPages: number;
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
maxVisiblePages?: number;
|
|
7
|
+
locale?: Locale;
|
|
8
|
+
}
|
|
9
|
+
export default function Paginator({ currentPage, totalPages, baseUrl, maxVisiblePages, locale, }: PaginatorProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import Link from "next/link";
|
|
3
|
+
import { getTranslator } from "../../utils";
|
|
4
|
+
import styles from "./index.module.css";
|
|
5
|
+
import { buildPageRange, getPageUrl, normalizeBaseUrl, } from "./index.utils";
|
|
6
|
+
export default function Paginator({ currentPage, totalPages, baseUrl, maxVisiblePages = 5, locale, }) {
|
|
7
|
+
if (totalPages <= 1) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const t = getTranslator(locale);
|
|
11
|
+
const pages = buildPageRange({ currentPage, totalPages, maxVisiblePages });
|
|
12
|
+
const hasPrev = currentPage > 1;
|
|
13
|
+
const hasNext = currentPage < totalPages;
|
|
14
|
+
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
15
|
+
return (_jsxs("nav", { className: styles.nav, "aria-label": t("paginator.aria"), children: [hasPrev && (_jsxs(Link, { href: getPageUrl(normalizedBaseUrl, currentPage - 1), className: "paginator-nav", children: ["\u2190 ", t("paginator.prev")] })), pages[0] > 1 && (_jsxs(_Fragment, { children: [_jsx(Link, { href: getPageUrl(normalizedBaseUrl, 1), className: "paginator-page", children: "1" }), pages[0] > 2 && _jsx("span", { className: styles.ellipsis, children: "\u2026" })] })), pages.map((page) => (_jsx(Link, { href: getPageUrl(normalizedBaseUrl, page), className: `paginator-page ${currentPage === page ? "paginator-active" : ""}`, "aria-current": currentPage === page ? "page" : undefined, children: page }, page))), pages[pages.length - 1] < totalPages && (_jsxs(_Fragment, { children: [pages[pages.length - 1] < totalPages - 1 && (_jsx("span", { className: styles.ellipsis, children: "\u2026" })), _jsx(Link, { href: getPageUrl(normalizedBaseUrl, totalPages), className: "paginator-page", children: totalPages })] })), hasNext && (_jsxs(Link, { href: getPageUrl(normalizedBaseUrl, currentPage + 1), className: "paginator-nav", children: [t("paginator.next"), " \u2192"] }))] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const normalizeBaseUrl: (url: string) => string;
|
|
2
|
+
export declare const getPageUrl: (base: string, page: number) => string;
|
|
3
|
+
export declare const buildPageRange: ({ currentPage, totalPages, maxVisiblePages, }: {
|
|
4
|
+
currentPage: number;
|
|
5
|
+
totalPages: number;
|
|
6
|
+
maxVisiblePages: number;
|
|
7
|
+
}) => number[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const normalizeBaseUrl = (url) => {
|
|
2
|
+
if (!url)
|
|
3
|
+
return "/";
|
|
4
|
+
const trimmed = url.replace(/\/+$/, "");
|
|
5
|
+
return `${trimmed}/`;
|
|
6
|
+
};
|
|
7
|
+
export const getPageUrl = (base, page) => page === 1 ? base : `${base}page/${page}/`;
|
|
8
|
+
export const buildPageRange = ({ currentPage, totalPages, maxVisiblePages, }) => {
|
|
9
|
+
const pages = [];
|
|
10
|
+
let start = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
|
|
11
|
+
const end = Math.min(totalPages, start + maxVisiblePages - 1);
|
|
12
|
+
if (end - start < maxVisiblePages - 1) {
|
|
13
|
+
start = Math.max(1, end - maxVisiblePages + 1);
|
|
14
|
+
}
|
|
15
|
+
for (let i = start; i <= end; i++) {
|
|
16
|
+
pages.push(i);
|
|
17
|
+
}
|
|
18
|
+
return pages;
|
|
19
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WPPost } from "wpjsapi-lib";
|
|
2
|
+
import { type Locale } from "../../utils";
|
|
3
|
+
interface PostCardProps {
|
|
4
|
+
post: WPPost;
|
|
5
|
+
categorySlug?: string;
|
|
6
|
+
locale?: Locale;
|
|
7
|
+
dateLocale?: string;
|
|
8
|
+
}
|
|
9
|
+
export default function PostCard({ post, categorySlug, locale, dateLocale, }: PostCardProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Image from "next/image";
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { getFeaturedMedia } from "../../utils";
|
|
5
|
+
import { buildCategoryUrl, buildPostUrl, formatPostDate, resolveCategorySlug, } from "./index.utils";
|
|
6
|
+
import styles from "./index.module.css";
|
|
7
|
+
export default function PostCard({ post, categorySlug, locale = "en", dateLocale = "en-US", }) {
|
|
8
|
+
const featuredMedia = getFeaturedMedia(post);
|
|
9
|
+
const imageUrl = featuredMedia?.source_url;
|
|
10
|
+
const categories = (post._embedded?.["wp:term"]?.[0] || []).filter((cat) => Boolean(cat?.slug));
|
|
11
|
+
const resolvedCategory = resolveCategorySlug(post, categorySlug);
|
|
12
|
+
const postUrl = buildPostUrl({
|
|
13
|
+
post,
|
|
14
|
+
categorySlug: resolvedCategory,
|
|
15
|
+
locale,
|
|
16
|
+
});
|
|
17
|
+
return (_jsxs("article", { className: `${styles.card} card`, children: [categories.length > 0 && (_jsx("div", { className: styles.badges, children: categories.map((cat) => (_jsx(Link, { href: buildCategoryUrl(cat.slug, locale), className: `badge ${styles.badge}`, children: cat.name }, cat.id ?? cat.slug))) })), _jsxs(Link, { href: postUrl, className: styles.postLink, children: [imageUrl && (_jsx("div", { className: styles.imageWrapper, children: _jsx(Image, { src: imageUrl, alt: featuredMedia?.alt_text || post.title.rendered, fill: true, style: { objectFit: "cover" }, sizes: "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" }) })), _jsxs("div", { className: styles.body, children: [_jsx("h2", { dangerouslySetInnerHTML: {
|
|
18
|
+
__html: post.title.rendered,
|
|
19
|
+
}, className: styles.title }), _jsx("div", { dangerouslySetInnerHTML: {
|
|
20
|
+
__html: post.excerpt.rendered,
|
|
21
|
+
}, className: styles.excerpt }), _jsx("time", { dateTime: post.date, className: styles.date, children: formatPostDate(post.date, dateLocale) })] })] })] }));
|
|
22
|
+
}
|