wpheadless-lib 1.1.9 → 1.1.11

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.
Files changed (119) hide show
  1. package/dist/api/categories.d.ts +1 -1
  2. package/dist/api/categories.js +18 -2
  3. package/dist/api/index.d.ts +7 -6
  4. package/dist/api/index.js +7 -6
  5. package/dist/api/mappers.d.ts +1 -1
  6. package/dist/api/mappers.js +1 -1
  7. package/dist/api/menus.d.ts +18 -0
  8. package/dist/api/menus.js +39 -0
  9. package/dist/api/posts.js +30 -2
  10. package/dist/api/translations.js +7 -1
  11. package/dist/api/wpClient.d.ts +5 -8
  12. package/dist/api/wpClient.js +14 -0
  13. package/dist/app/config.d.ts +2 -1
  14. package/dist/app/config.js +4 -0
  15. package/dist/app/globals.css +33 -121
  16. package/dist/base/category/index.d.ts +3 -3
  17. package/dist/base/category/index.js +9 -8
  18. package/dist/base/category/pagination.d.ts +2 -2
  19. package/dist/base/category/pagination.js +12 -10
  20. package/dist/base/home/index.js +1 -1
  21. package/dist/base/home/pagination.js +3 -3
  22. package/dist/base/index.d.ts +7 -7
  23. package/dist/base/index.js +7 -7
  24. package/dist/base/layout/RootLayoutBase.d.ts +6 -7
  25. package/dist/base/layout/RootLayoutBase.js +4 -4
  26. package/dist/base/layout/RootLayoutBase.module.css +10 -0
  27. package/dist/base/legal/index.d.ts +4 -4
  28. package/dist/base/legal/index.js +36 -24
  29. package/dist/base/post/index.d.ts +1 -1
  30. package/dist/base/post/index.js +15 -12
  31. package/dist/components/Breadcrumbs/index.js +4 -4
  32. package/dist/components/JsonLd.d.ts +5 -0
  33. package/dist/components/JsonLd.js +9 -0
  34. package/dist/components/Paginator/index.d.ts +1 -1
  35. package/dist/components/Paginator/index.js +5 -5
  36. package/dist/components/PostCard/index.d.ts +3 -2
  37. package/dist/components/PostCard/index.js +8 -6
  38. package/dist/components/PostCard/index.module.css +7 -7
  39. package/dist/components/PostCard/index.types.d.ts +2 -1
  40. package/dist/components/PostCard/index.utils.d.ts +5 -5
  41. package/dist/components/PostCard/index.utils.js +8 -6
  42. package/dist/components/index.d.ts +6 -5
  43. package/dist/components/index.js +6 -5
  44. package/dist/components/layout/Footer/index.d.ts +5 -5
  45. package/dist/components/layout/Footer/index.js +11 -22
  46. package/dist/components/layout/Footer/index.module.css +59 -9
  47. package/dist/components/layout/Header/HeaderClient.d.ts +1 -1
  48. package/dist/components/layout/Header/HeaderClient.js +22 -2
  49. package/dist/components/layout/Header/index.d.ts +5 -5
  50. package/dist/components/layout/Header/index.js +10 -29
  51. package/dist/components/layout/Header/index.module.css +77 -16
  52. package/dist/components/ui/alert.d.ts +8 -0
  53. package/dist/components/ui/alert.js +12 -0
  54. package/dist/components/ui/alert.module.css +26 -0
  55. package/dist/components/ui/badge.d.ts +3 -0
  56. package/dist/components/ui/badge.js +9 -0
  57. package/dist/components/ui/badge.module.css +23 -0
  58. package/dist/components/ui/breadcrumb.d.ts +8 -0
  59. package/dist/components/ui/breadcrumb.js +22 -0
  60. package/dist/components/ui/breadcrumb.module.css +37 -0
  61. package/dist/components/ui/button.d.ts +7 -0
  62. package/dist/components/ui/button.js +16 -0
  63. package/dist/components/ui/button.module.css +72 -0
  64. package/dist/components/ui/card.d.ts +11 -0
  65. package/dist/components/ui/card.js +16 -0
  66. package/dist/components/ui/card.module.css +37 -0
  67. package/dist/components/ui/cn.d.ts +1 -0
  68. package/dist/components/ui/cn.js +3 -0
  69. package/dist/components/ui/index.d.ts +6 -0
  70. package/dist/components/ui/index.js +6 -0
  71. package/dist/components/ui/pagination.d.ts +14 -0
  72. package/dist/components/ui/pagination.js +25 -0
  73. package/dist/components/ui/pagination.module.css +62 -0
  74. package/dist/index.d.ts +6 -6
  75. package/dist/index.js +6 -6
  76. package/dist/plugins/index.d.ts +1 -1
  77. package/dist/plugins/index.js +1 -1
  78. package/dist/plugins/yoast/index.js +10 -7
  79. package/dist/utils/hreflang.d.ts +4 -7
  80. package/dist/utils/hreflang.js +11 -6
  81. package/dist/utils/html.d.ts +2 -0
  82. package/dist/utils/html.js +25 -0
  83. package/dist/utils/index.d.ts +7 -6
  84. package/dist/utils/index.js +7 -6
  85. package/dist/utils/language.d.ts +37 -0
  86. package/dist/utils/language.js +75 -0
  87. package/dist/utils/seo.d.ts +1 -6
  88. package/dist/utils/seo.js +76 -12
  89. package/dist/utils/sitemap.d.ts +1 -1
  90. package/dist/utils/sitemap.js +107 -56
  91. package/dist/views/CategoryListView/index.d.ts +1 -1
  92. package/dist/views/CategoryListView/index.js +6 -6
  93. package/dist/views/CategoryListView/index.utils.d.ts +1 -1
  94. package/dist/views/CategoryListView/index.utils.js +1 -1
  95. package/dist/views/CategoryPaginationView/index.d.ts +1 -1
  96. package/dist/views/CategoryPaginationView/index.js +6 -6
  97. package/dist/views/CategoryPaginationView/index.utils.d.ts +1 -1
  98. package/dist/views/CategoryPaginationView/index.utils.js +1 -1
  99. package/dist/views/HomePaginationView/index.d.ts +1 -1
  100. package/dist/views/HomePaginationView/index.js +5 -4
  101. package/dist/views/HomePaginationView/index.utils.d.ts +1 -1
  102. package/dist/views/HomePaginationView/index.utils.js +1 -1
  103. package/dist/views/HomeView/index.d.ts +1 -1
  104. package/dist/views/HomeView/index.js +13 -12
  105. package/dist/views/HomeView/index.module.css +51 -8
  106. package/dist/views/HomeView/index.utils.d.ts +1 -1
  107. package/dist/views/HomeView/index.utils.js +2 -2
  108. package/dist/views/LegalPageView/index.d.ts +2 -1
  109. package/dist/views/LegalPageView/index.js +5 -5
  110. package/dist/views/LegalPageView/index.module.css +3 -3
  111. package/dist/views/LegalPageView/index.utils.js +1 -1
  112. package/dist/views/PostView/index.d.ts +3 -2
  113. package/dist/views/PostView/index.js +9 -7
  114. package/dist/views/PostView/index.module.css +46 -13
  115. package/dist/views/PostView/index.utils.d.ts +3 -3
  116. package/dist/views/PostView/index.utils.js +2 -2
  117. package/dist/views/index.d.ts +6 -6
  118. package/dist/views/index.js +6 -6
  119. package/package.json +47 -10
@@ -1,7 +1,7 @@
1
- export * from "./layout/RootLayoutBase";
2
- export * from "./home";
3
- export * from "./home/pagination";
4
- export * from "./legal";
5
- export * from "./category/pagination";
6
- export * from "./category";
7
- export * from "./post";
1
+ export * from "./layout/RootLayoutBase.js";
2
+ export * from "./home/index.js";
3
+ export * from "./home/pagination.js";
4
+ export * from "./legal/index.js";
5
+ export * from "./category/pagination.js";
6
+ export * from "./category/index.js";
7
+ export * from "./post/index.js";
@@ -1,7 +1,7 @@
1
- export * from "./layout/RootLayoutBase";
2
- export * from "./home";
3
- export * from "./home/pagination";
4
- export * from "./legal";
5
- export * from "./category/pagination";
6
- export * from "./category";
7
- export * from "./post";
1
+ export * from "./layout/RootLayoutBase.js";
2
+ export * from "./home/index.js";
3
+ export * from "./home/pagination.js";
4
+ export * from "./legal/index.js";
5
+ export * from "./category/pagination.js";
6
+ export * from "./category/index.js";
7
+ export * from "./post/index.js";
@@ -1,6 +1,5 @@
1
1
  import type { ReactNode } from "react";
2
- import "../../app/globals.css";
3
- import type { LogoProps } from "../../components/layout/types";
2
+ import type { LogoProps } from "../../components/layout/types.js";
4
3
  export declare const fontClassName = "";
5
4
  export declare const viewport: {
6
5
  width: string;
@@ -10,12 +9,12 @@ export declare const viewport: {
10
9
  };
11
10
  type RootLayoutBaseProps = {
12
11
  children: ReactNode;
13
- menuHeaderId: string;
14
- menuFooterId: string;
12
+ menuHeaderId?: string;
13
+ menuFooterId?: string;
15
14
  siteName: string;
16
- wpApiUrl: string;
17
- wpUsername: string;
18
- wpAppPassword: string;
15
+ wpApiUrl?: string;
16
+ wpUsername?: string;
17
+ wpAppPassword?: string;
19
18
  homeHref?: string;
20
19
  locale?: string;
21
20
  headerLogo?: LogoProps;
@@ -1,7 +1,7 @@
1
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";
2
+ import Header from "../../components/layout/Header/index.js";
3
+ import Footer from "../../components/layout/Footer/index.js";
4
+ import styles from "./RootLayoutBase.module.css";
5
5
  // Use system fonts to avoid external downloads during build.
6
6
  export const fontClassName = "";
7
7
  export const viewport = {
@@ -11,5 +11,5 @@ export const viewport = {
11
11
  themeColor: "#333333",
12
12
  };
13
13
  export function RootLayoutBase({ children, menuHeaderId, menuFooterId, siteName, wpApiUrl, wpUsername, wpAppPassword, homeHref, locale, headerLogo, footerLogo, }) {
14
- return (_jsxs(_Fragment, { children: [_jsx(Header, { menuId: menuHeaderId, wpApiUrl: wpApiUrl, wpUsername: wpUsername, wpAppPassword: wpAppPassword, siteName: siteName, homeHref: homeHref, locale: locale, logo: headerLogo }), _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, logo: footerLogo })] }));
14
+ return (_jsxs(_Fragment, { children: [_jsx(Header, { menuId: menuHeaderId, wpApiUrl: wpApiUrl, wpUsername: wpUsername, wpAppPassword: wpAppPassword, siteName: siteName, homeHref: homeHref, locale: locale, logo: headerLogo }), _jsx("main", { id: "main-content", className: styles.main, children: _jsx("div", { className: styles.mainContainer, children: children }) }), _jsx(Footer, { menuId: menuFooterId, wpApiUrl: wpApiUrl, wpUsername: wpUsername, wpAppPassword: wpAppPassword, siteName: siteName, locale: locale, logo: footerLogo })] }));
15
15
  }
@@ -0,0 +1,10 @@
1
+ .main {
2
+ min-height: calc(100vh - 200px);
3
+ }
4
+
5
+ .mainContainer {
6
+ width: 100%;
7
+ max-width: var(--container-width);
8
+ margin: 0 auto;
9
+ padding-inline: clamp(1rem, 4vw, 2rem);
10
+ }
@@ -1,15 +1,15 @@
1
1
  import { type WPPage } from "wpjsapi-lib";
2
2
  import type { Metadata } from "next";
3
- import { LanguageConfig } from "../../utils/hreflang";
3
+ import { LanguageConfig } from "../../utils/hreflang.js";
4
4
  type StaticParams = Array<{
5
5
  slug: string;
6
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>;
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
9
  export declare function fetchPagesByTranslateKey({ baseApiUrl, translationKey, lang, langId, }: {
10
10
  baseApiUrl: string;
11
11
  translationKey: string;
12
- lang: string;
12
+ lang?: string;
13
13
  langId?: string;
14
14
  }): Promise<WPPage[]>;
15
15
  export declare function buildLegalMetadata({ page, slug, canonicalBase, useYoast, siteName, languages, siteUrl, wpApiUrl, }: {
@@ -1,8 +1,11 @@
1
1
  import { createPageEndpoints } from "wpjsapi-lib";
2
- import { getAbsoluteUrl, getFeaturedMedia, getPlainTextExcerpt, getYoastHead, buildYoastRobotsMeta, } from "../../utils";
3
- import { buildLanguageAlternatesPerLanguage, buildAbsoluteLangUrl, getEntityLanguageId, withXDefault, getTranslationKey, } from "../../utils/hreflang";
4
- import { mapPageEntity } from "../../api/mappers";
2
+ import { getAbsoluteUrl, getFeaturedMedia, getPlainTextExcerpt, getYoastHead, buildYoastRobotsMeta, toPlainText, } from "../../utils/index.js";
3
+ import { buildLanguageAlternatesPerLanguage, buildAbsoluteLangUrl, getEntityLanguageId, withXDefault, getTranslationKey, } from "../../utils/hreflang.js";
4
+ import { mapPageEntity } from "../../api/mappers.js";
5
+ import { isValidWpApiUrl } from "../../api/wpClient.js";
5
6
  async function getLegalParentId(baseApiUrl, lang, langId) {
7
+ if (!isValidWpApiUrl(baseApiUrl))
8
+ return null;
6
9
  const pagesApi = createPageEndpoints({ baseUrl: baseApiUrl });
7
10
  try {
8
11
  const parent = await pagesApi.list({
@@ -19,16 +22,18 @@ async function getLegalParentId(baseApiUrl, lang, langId) {
19
22
  }
20
23
  }
21
24
  export async function getLegalStaticParams(baseApiUrl, lang, langId) {
22
- const pagesApi = createPageEndpoints({
23
- baseUrl: baseApiUrl,
24
- });
25
+ if (!isValidWpApiUrl(baseApiUrl))
26
+ return [];
25
27
  try {
28
+ const pagesApi = createPageEndpoints({
29
+ baseUrl: baseApiUrl,
30
+ });
26
31
  const parentId = await getLegalParentId(baseApiUrl, lang, langId);
27
32
  if (!parentId)
28
33
  return [];
29
34
  const pages = await pagesApi.listAll({
30
35
  parent: parentId,
31
- lang,
36
+ ...(lang ? { lang } : {}),
32
37
  _fields: ["slug"],
33
38
  });
34
39
  return pages.map((page) => ({
@@ -41,10 +46,12 @@ export async function getLegalStaticParams(baseApiUrl, lang, langId) {
41
46
  }
42
47
  }
43
48
  export async function fetchLegalPage(baseApiUrl, slug, lang, langId) {
44
- const pagesApi = createPageEndpoints({
45
- baseUrl: baseApiUrl,
46
- });
49
+ if (!isValidWpApiUrl(baseApiUrl))
50
+ return null;
47
51
  try {
52
+ const pagesApi = createPageEndpoints({
53
+ baseUrl: baseApiUrl,
54
+ });
48
55
  const parentId = await getLegalParentId(baseApiUrl, lang, langId);
49
56
  if (!parentId)
50
57
  return null;
@@ -53,7 +60,7 @@ export async function fetchLegalPage(baseApiUrl, slug, lang, langId) {
53
60
  per_page: 1,
54
61
  _embed: true,
55
62
  parent: parentId,
56
- lang,
63
+ ...(lang ? { lang } : {}),
57
64
  });
58
65
  if (response.items.length === 0) {
59
66
  return null;
@@ -66,10 +73,12 @@ export async function fetchLegalPage(baseApiUrl, slug, lang, langId) {
66
73
  }
67
74
  }
68
75
  export async function fetchPagesByTranslateKey({ baseApiUrl, translationKey, lang, langId, }) {
69
- const pagesApi = createPageEndpoints({
70
- baseUrl: baseApiUrl,
71
- });
76
+ if (!isValidWpApiUrl(baseApiUrl))
77
+ return [];
72
78
  try {
79
+ const pagesApi = createPageEndpoints({
80
+ baseUrl: baseApiUrl,
81
+ });
73
82
  const parentId = await getLegalParentId(baseApiUrl, lang, langId);
74
83
  if (!parentId)
75
84
  return [];
@@ -78,7 +87,7 @@ export async function fetchPagesByTranslateKey({ baseApiUrl, translationKey, lan
78
87
  _embed: true,
79
88
  translation_key_v2: translationKey,
80
89
  parent: parentId,
81
- lang,
90
+ ...(lang ? { lang } : {}),
82
91
  });
83
92
  const filtered = response.items.filter((item) => getTranslationKey(item) === translationKey);
84
93
  return filtered.length > 0 ? filtered : response.items;
@@ -92,17 +101,18 @@ export function buildLegalMetadata({ page, slug, canonicalBase, useYoast = true,
92
101
  const url = getAbsoluteUrl(`${canonicalBase}legal/${slug}`, siteUrl);
93
102
  const featuredMedia = getFeaturedMedia(page);
94
103
  const fallbackDescription = getPlainTextExcerpt(page.excerpt.rendered, 160);
104
+ const fallbackTitle = toPlainText(page.title.rendered) || page.title.rendered;
95
105
  const imageUrl = featuredMedia?.source_url;
96
106
  const languageAlternates = withXDefault(languages);
97
107
  const baseMetadata = {
98
- title: page.title.rendered,
108
+ title: fallbackTitle,
99
109
  description: fallbackDescription,
100
110
  alternates: {
101
111
  canonical: url,
102
112
  ...(languageAlternates ? { languages: languageAlternates } : {}),
103
113
  },
104
114
  openGraph: {
105
- title: page.title.rendered,
115
+ title: fallbackTitle,
106
116
  description: fallbackDescription,
107
117
  url,
108
118
  siteName,
@@ -111,7 +121,7 @@ export function buildLegalMetadata({ page, slug, canonicalBase, useYoast = true,
111
121
  },
112
122
  twitter: {
113
123
  card: "summary_large_image",
114
- title: page.title.rendered,
124
+ title: fallbackTitle,
115
125
  description: fallbackDescription,
116
126
  images: imageUrl ? [imageUrl] : undefined,
117
127
  },
@@ -122,16 +132,17 @@ export function buildLegalMetadata({ page, slug, canonicalBase, useYoast = true,
122
132
  const yoastImageUrl = yoast?.og_image?.[0]?.url || imageUrl;
123
133
  const robots = buildYoastRobotsMeta(yoast?.robots);
124
134
  return {
125
- title: yoast?.title || page.title.rendered,
126
- description: yoast?.description || fallbackDescription,
135
+ title: toPlainText(yoast?.title) || fallbackTitle,
136
+ description: toPlainText(yoast?.description) || fallbackDescription,
127
137
  ...(robots ? { robots } : {}),
128
138
  alternates: {
129
139
  canonical: url,
130
140
  ...(languageAlternates ? { languages: languageAlternates } : {}),
131
141
  },
132
142
  openGraph: {
133
- title: yoast?.og_title || yoast?.title || page.title.rendered,
134
- description: yoast?.og_description || yoast?.description || fallbackDescription,
143
+ title: toPlainText(yoast?.og_title || yoast?.title) || fallbackTitle,
144
+ description: toPlainText(yoast?.og_description || yoast?.description) ||
145
+ fallbackDescription,
135
146
  url,
136
147
  siteName: yoast?.og_site_name,
137
148
  type: yoast?.og_type || "website",
@@ -139,8 +150,9 @@ export function buildLegalMetadata({ page, slug, canonicalBase, useYoast = true,
139
150
  },
140
151
  twitter: {
141
152
  card: yoast?.twitter_card || "summary_large_image",
142
- title: yoast?.twitter_title || yoast?.title || page.title.rendered,
143
- description: yoast?.twitter_description || yoast?.description || fallbackDescription,
153
+ title: toPlainText(yoast?.twitter_title || yoast?.title) || fallbackTitle,
154
+ description: toPlainText(yoast?.twitter_description || yoast?.description) ||
155
+ fallbackDescription,
144
156
  images: yoastImageUrl ? [yoastImageUrl] : undefined,
145
157
  },
146
158
  };
@@ -2,7 +2,7 @@ import { type WPPost } from "wpjsapi-lib";
2
2
  import type { Metadata } from "next";
3
3
  type PostStaticParamsInput = {
4
4
  baseApiUrl: string;
5
- lang: string;
5
+ lang?: string;
6
6
  langId?: string;
7
7
  };
8
8
  type PostStaticParam = {
@@ -1,6 +1,6 @@
1
- import { getFeaturedMedia, getOgImageUrl, getPlainTextExcerpt, getYoastHead, buildYoastRobotsMeta, } from "../../utils";
2
- import { getPostBySlug as getPostBySlugApi, listPostStaticParams, listPostsByTranslationKey, } from "../../api/posts";
3
- import { withXDefault } from "../../utils/hreflang";
1
+ import { getFeaturedMedia, getOgImageUrl, getPlainTextExcerpt, getYoastHead, buildYoastRobotsMeta, toPlainText, } from "../../utils/index.js";
2
+ import { getPostBySlug as getPostBySlugApi, listPostStaticParams, listPostsByTranslationKey, } from "../../api/posts.js";
3
+ import { withXDefault } from "../../utils/hreflang.js";
4
4
  export async function getPostStaticParams({ baseApiUrl, lang, langId, }) {
5
5
  const result = await listPostStaticParams({
6
6
  baseApiUrl,
@@ -44,16 +44,17 @@ export function buildPostMetadata({ post, canonical, useYoast = true, siteName,
44
44
  const featuredMedia = getFeaturedMedia(post);
45
45
  const imageUrl = getOgImageUrl(post, featuredMedia);
46
46
  const fallbackDescription = getPlainTextExcerpt(post.excerpt?.rendered, 160);
47
+ const fallbackTitle = toPlainText(post.title.rendered) || post.title.rendered;
47
48
  const languageAlternates = withXDefault(languages);
48
49
  const fallbackMeta = {
49
- title: post.title.rendered,
50
+ title: fallbackTitle,
50
51
  description: fallbackDescription,
51
52
  alternates: {
52
53
  canonical,
53
54
  ...(languageAlternates ? { languages: languageAlternates } : {}),
54
55
  },
55
56
  openGraph: {
56
- title: post.title.rendered,
57
+ title: fallbackTitle,
57
58
  description: fallbackDescription,
58
59
  url: canonical,
59
60
  type: "article",
@@ -62,7 +63,7 @@ export function buildPostMetadata({ post, canonical, useYoast = true, siteName,
62
63
  },
63
64
  twitter: {
64
65
  card: "summary_large_image",
65
- title: post.title.rendered,
66
+ title: fallbackTitle,
66
67
  description: fallbackDescription,
67
68
  images: imageUrl ? [imageUrl] : undefined,
68
69
  },
@@ -74,16 +75,17 @@ export function buildPostMetadata({ post, canonical, useYoast = true, siteName,
74
75
  return fallbackMeta;
75
76
  const robots = buildYoastRobotsMeta(yoast.robots);
76
77
  return {
77
- title: yoast.title || post.title.rendered,
78
- description: yoast.description || fallbackDescription,
78
+ title: toPlainText(yoast.title) || fallbackTitle,
79
+ description: toPlainText(yoast.description) || fallbackDescription,
79
80
  ...(robots ? { robots } : {}),
80
81
  alternates: {
81
82
  canonical,
82
83
  ...(languageAlternates ? { languages: languageAlternates } : {}),
83
84
  },
84
85
  openGraph: {
85
- title: yoast.og_title || yoast.title || post.title.rendered,
86
- description: yoast.og_description || yoast.description || fallbackDescription,
86
+ title: toPlainText(yoast.og_title || yoast.title) || fallbackTitle,
87
+ description: toPlainText(yoast.og_description || yoast.description) ||
88
+ fallbackDescription,
87
89
  url: canonical,
88
90
  type: yoast.og_type || "article",
89
91
  siteName: yoast.og_site_name,
@@ -91,8 +93,9 @@ export function buildPostMetadata({ post, canonical, useYoast = true, siteName,
91
93
  },
92
94
  twitter: {
93
95
  card: yoast.twitter_card || "summary_large_image",
94
- title: yoast.twitter_title || yoast.title || post.title.rendered,
95
- description: yoast.twitter_description || yoast.description || fallbackDescription,
96
+ title: toPlainText(yoast.twitter_title || yoast.title) || fallbackTitle,
97
+ description: toPlainText(yoast.twitter_description || yoast.description) ||
98
+ fallbackDescription,
96
99
  images: imageUrl ? [imageUrl] : undefined,
97
100
  },
98
101
  };
@@ -1,16 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import Link from "next/link";
3
2
  import styles from "./index.module.css";
3
+ import { Breadcrumb, BreadcrumbItem as BreadcrumbListItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "../ui/index.js";
4
4
  function truncateLabel(label, max = 30) {
5
5
  const trimmed = label.trim();
6
- return trimmed.length > max ? `${trimmed.slice(0, max)}...` : trimmed;
6
+ return trimmed.length > max ? `${trimmed.slice(0, max)}…` : trimmed;
7
7
  }
8
8
  export function Breadcrumbs({ items }) {
9
9
  if (!items.length)
10
10
  return null;
11
- return (_jsx("nav", { "aria-label": "Breadcrumb", className: styles.nav, children: _jsx("ol", { className: styles.list, children: items.map((item, idx) => {
11
+ return (_jsx(Breadcrumb, { className: styles.nav, children: _jsx(BreadcrumbList, { className: styles.list, children: items.map((item, idx) => {
12
12
  const isLast = idx === items.length - 1;
13
13
  const display = truncateLabel(item.label, 30);
14
- return (_jsxs("li", { className: styles.item, children: [item.href && !isLast ? (_jsx(Link, { href: item.href, className: styles.link, title: item.label, children: display })) : (_jsx("span", { className: styles.current, "aria-current": isLast ? "page" : undefined, title: item.label, children: display })), idx < items.length - 1 && (_jsx("span", { className: styles.separator, children: "/" }))] }, `${item.label}-${idx}`));
14
+ return (_jsxs(BreadcrumbListItem, { className: styles.item, children: [item.href && !isLast ? (_jsx(BreadcrumbLink, { href: item.href, className: styles.link, title: item.label, children: display })) : (_jsx(BreadcrumbPage, { className: styles.current, title: item.label, children: display })), idx < items.length - 1 && (_jsx(BreadcrumbSeparator, { className: styles.separator }))] }, `${item.label}-${idx}`));
15
15
  }) }) }));
16
16
  }
@@ -0,0 +1,5 @@
1
+ type JsonLdProps = {
2
+ data?: unknown;
3
+ };
4
+ export declare function JsonLd({ data }: JsonLdProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const escapeJsonForHtml = (value) => value.replace(/</g, "\\u003c").replace(/>/g, "\\u003e");
3
+ export function JsonLd({ data }) {
4
+ if (!data)
5
+ return null;
6
+ return (_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: {
7
+ __html: escapeJsonForHtml(JSON.stringify(data)),
8
+ } }));
9
+ }
@@ -1,4 +1,4 @@
1
- import { type Locale } from "../../utils";
1
+ import { type Locale } from "../../utils/index.js";
2
2
  interface PaginatorProps {
3
3
  currentPage: number;
4
4
  totalPages: number;
@@ -1,8 +1,8 @@
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";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { getTranslator } from "../../utils/index.js";
4
3
  import styles from "./index.module.css";
5
- import { buildPageRange, getPageUrl, normalizeBaseUrl, } from "./index.utils";
4
+ import { buildPageRange, getPageUrl, normalizeBaseUrl, } from "./index.utils.js";
5
+ import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from "../ui/index.js";
6
6
  export default function Paginator({ currentPage, totalPages, baseUrl, maxVisiblePages = 5, locale, }) {
7
7
  if (totalPages <= 1) {
8
8
  return null;
@@ -12,5 +12,5 @@ export default function Paginator({ currentPage, totalPages, baseUrl, maxVisible
12
12
  const hasPrev = currentPage > 1;
13
13
  const hasNext = currentPage < totalPages;
14
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"] }))] }));
15
+ return (_jsx(Pagination, { className: styles.nav, "aria-label": t("paginator.aria"), children: _jsxs(PaginationContent, { children: [hasPrev && (_jsx(PaginationItem, { children: _jsx(PaginationPrevious, { href: getPageUrl(normalizedBaseUrl, currentPage - 1), children: t("paginator.prev") }) })), pages[0] > 1 && (_jsxs(_Fragment, { children: [_jsx(PaginationItem, { children: _jsx(PaginationLink, { href: getPageUrl(normalizedBaseUrl, 1), children: "1" }) }), pages[0] > 2 && (_jsx(PaginationItem, { children: _jsx(PaginationEllipsis, { className: styles.ellipsis }) }))] })), pages.map((page) => (_jsx(PaginationItem, { children: _jsx(PaginationLink, { href: getPageUrl(normalizedBaseUrl, page), isActive: currentPage === page, children: page }) }, page))), pages[pages.length - 1] < totalPages && (_jsxs(_Fragment, { children: [pages[pages.length - 1] < totalPages - 1 && (_jsx(PaginationItem, { children: _jsx(PaginationEllipsis, { className: styles.ellipsis }) })), _jsx(PaginationItem, { children: _jsx(PaginationLink, { href: getPageUrl(normalizedBaseUrl, totalPages), children: totalPages }) })] })), hasNext && (_jsx(PaginationItem, { children: _jsx(PaginationNext, { href: getPageUrl(normalizedBaseUrl, currentPage + 1), children: t("paginator.next") }) }))] }) }));
16
16
  }
@@ -1,11 +1,12 @@
1
1
  import type { WPPost } from "wpjsapi-lib";
2
- import { type Locale } from "../../utils";
2
+ import { type Locale } from "../../utils/index.js";
3
3
  interface PostCardProps {
4
4
  post: WPPost;
5
5
  categorySlug?: string;
6
6
  locale?: Locale;
7
+ defaultLocale?: Locale;
7
8
  dateLocale?: string;
8
9
  basePath?: string;
9
10
  }
10
- export default function PostCard({ post, categorySlug, locale, dateLocale, basePath, }: PostCardProps): import("react/jsx-runtime").JSX.Element;
11
+ export default function PostCard({ post, categorySlug, locale, defaultLocale, dateLocale, basePath, }: PostCardProps): import("react/jsx-runtime").JSX.Element;
11
12
  export {};
@@ -1,14 +1,15 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import Image from "next/image";
3
3
  import Link from "next/link";
4
- import { getFeaturedMedia } from "../../utils";
5
- import { buildCategoryUrl, buildPostUrl, formatPostDate, resolveCategorySlug, } from "./index.utils";
4
+ import { getFeaturedMedia } from "../../utils/index.js";
5
+ import { buildCategoryUrl, buildPostUrl, formatPostDate, resolveCategorySlug, } from "./index.utils.js";
6
6
  import styles from "./index.module.css";
7
+ import { badgeClassName, Card, CardContent } from "../ui/index.js";
7
8
  function truncateText(text, max = 20) {
8
9
  const normalized = text.trim();
9
- return normalized.length > max ? `${normalized.slice(0, max)}...` : normalized;
10
+ return normalized.length > max ? `${normalized.slice(0, max)}…` : normalized;
10
11
  }
11
- export default function PostCard({ post, categorySlug, locale = "en", dateLocale = "en-US", basePath, }) {
12
+ export default function PostCard({ post, categorySlug, locale = "en", defaultLocale, dateLocale = "en-US", basePath, }) {
12
13
  const featuredMedia = getFeaturedMedia(post);
13
14
  const imageUrl = featuredMedia?.source_url;
14
15
  const categories = (post._embedded?.["wp:term"]?.[0] || []).filter((cat) => Boolean(cat?.slug));
@@ -17,11 +18,12 @@ export default function PostCard({ post, categorySlug, locale = "en", dateLocale
17
18
  post,
18
19
  categorySlug: resolvedCategory,
19
20
  locale,
21
+ defaultLocale,
20
22
  basePath,
21
23
  });
22
- 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, basePath), className: `badge ${styles.badge}`, title: cat.name, children: truncateText(cat.name, 20) }, 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", { className: styles.title, dangerouslySetInnerHTML: {
24
+ return (_jsxs(Card, { as: "article", className: styles.card, children: [imageUrl && (_jsx(Link, { href: postUrl, className: styles.imageLink, children: _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(CardContent, { className: styles.body, children: [categories.length > 0 && (_jsx("div", { className: styles.badges, children: categories.map((cat) => (_jsx(Link, { href: buildCategoryUrl(cat.slug, locale, basePath, defaultLocale), className: badgeClassName(styles.badge), title: cat.name, children: truncateText(cat.name, 20) }, cat.id ?? cat.slug))) })), _jsxs(Link, { href: postUrl, className: styles.postLink, children: [_jsx("h2", { className: styles.title, dangerouslySetInnerHTML: {
23
25
  __html: post.title.rendered,
24
26
  } }), _jsx("div", { dangerouslySetInnerHTML: {
25
27
  __html: post.excerpt.rendered,
26
- }, className: styles.excerpt }), _jsx("time", { dateTime: post.date, className: styles.date, children: formatPostDate(post.date, dateLocale) })] })] })] }));
28
+ }, className: styles.excerpt })] }), _jsx("time", { dateTime: post.date, className: styles.date, children: formatPostDate(post.date, dateLocale) })] })] }));
27
29
  }
@@ -7,30 +7,30 @@
7
7
  }
8
8
 
9
9
  .badges {
10
- position: absolute;
11
- top: 12px;
12
- left: 12px;
13
- right: 12px;
14
10
  display: flex;
15
11
  gap: 0.5rem;
16
12
  flex-wrap: wrap;
17
- z-index: 2;
13
+ margin-bottom: 0.15rem;
18
14
  }
19
15
 
20
16
  .badge {
21
17
  text-decoration: none;
22
- box-shadow: 0 6px 16px var(--shadow);
18
+ box-shadow: none;
23
19
  }
24
20
 
21
+ .imageLink,
25
22
  .postLink {
26
23
  text-decoration: none;
27
24
  color: inherit;
28
25
  display: block;
29
- height: 100%;
30
26
  position: relative;
31
27
  z-index: 1;
32
28
  }
33
29
 
30
+ .postLink:hover .title {
31
+ color: var(--primary);
32
+ }
33
+
34
34
  .imageWrapper {
35
35
  position: relative;
36
36
  height: 220px;
@@ -1,8 +1,9 @@
1
1
  import type { WPPost } from "wpjsapi-lib";
2
- import { type Locale } from "../../utils";
2
+ import { type Locale } from "../../utils/index.js";
3
3
  export type BuildUrlArgs = {
4
4
  post: WPPost;
5
5
  categorySlug?: string;
6
6
  locale?: Locale;
7
+ defaultLocale?: Locale;
7
8
  basePath?: string;
8
9
  };
@@ -1,8 +1,8 @@
1
1
  import type { WPPost } from "wpjsapi-lib";
2
- import { type Locale } from "../../utils";
3
- import type { BuildUrlArgs } from "./index.types";
4
- export declare const getLangPrefix: (locale?: Locale) => string;
2
+ import { type Locale } from "../../utils/index.js";
3
+ import type { BuildUrlArgs } from "./index.types.js";
4
+ export declare const getLangPrefix: (locale?: Locale, defaultLocale?: Locale) => string;
5
5
  export declare const resolveCategorySlug: (post: WPPost, categorySlug?: string) => string | undefined;
6
- export declare const buildPostUrl: ({ post, categorySlug, locale, basePath, }: BuildUrlArgs) => string;
7
- export declare const buildCategoryUrl: (slug: string, locale?: Locale, basePath?: string) => string;
6
+ export declare const buildPostUrl: ({ post, categorySlug, locale, defaultLocale, basePath, }: BuildUrlArgs) => string;
7
+ export declare const buildCategoryUrl: (slug: string, locale?: Locale, basePath?: string, defaultLocale?: Locale) => string;
8
8
  export declare const formatPostDate: (date: string, dateLocale?: string) => string;
@@ -1,5 +1,5 @@
1
- import { ensureTrailingSlash } from "../../utils";
2
- export const getLangPrefix = (locale) => locale && locale !== "en" ? `/${locale}` : "";
1
+ import { ensureTrailingSlash } from "../../utils/index.js";
2
+ export const getLangPrefix = (locale, defaultLocale) => locale && defaultLocale && locale !== defaultLocale ? `/${locale}` : "";
3
3
  const normalizeBasePath = (basePath) => {
4
4
  if (!basePath)
5
5
  return "";
@@ -9,15 +9,17 @@ const normalizeBasePath = (basePath) => {
9
9
  const trimmed = withLeadingSlash.replace(/\/+$/, "");
10
10
  return trimmed === "/" ? "" : trimmed;
11
11
  };
12
- const resolveLinkPrefix = (basePath, locale) => basePath !== undefined ? normalizeBasePath(basePath) : getLangPrefix(locale);
12
+ const resolveLinkPrefix = (basePath, locale, defaultLocale) => basePath !== undefined
13
+ ? normalizeBasePath(basePath)
14
+ : getLangPrefix(locale, defaultLocale);
13
15
  export const resolveCategorySlug = (post, categorySlug) => {
14
16
  if (categorySlug)
15
17
  return categorySlug;
16
18
  const categories = (post._embedded?.["wp:term"]?.[0] || []);
17
19
  return categories[0]?.slug;
18
20
  };
19
- export const buildPostUrl = ({ post, categorySlug, locale, basePath, }) => {
20
- const langPrefix = resolveLinkPrefix(basePath, locale);
21
+ export const buildPostUrl = ({ post, categorySlug, locale, defaultLocale, basePath, }) => {
22
+ const langPrefix = resolveLinkPrefix(basePath, locale, defaultLocale);
21
23
  const resolvedCategory = categorySlug || resolveCategorySlug(post);
22
24
  const postPath = resolvedCategory
23
25
  ? `/${resolvedCategory}/${post.slug}`
@@ -25,7 +27,7 @@ export const buildPostUrl = ({ post, categorySlug, locale, basePath, }) => {
25
27
  const url = `${langPrefix}${postPath}`.replace(/\/+/g, "/");
26
28
  return ensureTrailingSlash(url);
27
29
  };
28
- export const buildCategoryUrl = (slug, locale, basePath) => ensureTrailingSlash(`${resolveLinkPrefix(basePath, locale)}/${slug}`.replace(/\/+/g, "/"));
30
+ export const buildCategoryUrl = (slug, locale, basePath, defaultLocale) => ensureTrailingSlash(`${resolveLinkPrefix(basePath, locale, defaultLocale)}/${slug}`.replace(/\/+/g, "/"));
29
31
  export const formatPostDate = (date, dateLocale) => new Date(date).toLocaleDateString(dateLocale || "en-US", {
30
32
  year: "numeric",
31
33
  month: "long",
@@ -1,5 +1,6 @@
1
- export { default as Header } from "./layout/Header";
2
- export { default as Footer } from "./layout/Footer";
3
- export { default as Paginator } from "./Paginator";
4
- export { default as PostCard } from "./PostCard";
5
- export { Breadcrumbs } from "./Breadcrumbs";
1
+ export { default as Header } from "./layout/Header/index.js";
2
+ export { default as Footer } from "./layout/Footer/index.js";
3
+ export { default as Paginator } from "./Paginator/index.js";
4
+ export { default as PostCard } from "./PostCard/index.js";
5
+ export { Breadcrumbs } from "./Breadcrumbs/index.js";
6
+ export { JsonLd } from "./JsonLd.js";
@@ -1,5 +1,6 @@
1
- export { default as Header } from "./layout/Header";
2
- export { default as Footer } from "./layout/Footer";
3
- export { default as Paginator } from "./Paginator";
4
- export { default as PostCard } from "./PostCard";
5
- export { Breadcrumbs } from "./Breadcrumbs";
1
+ export { default as Header } from "./layout/Header/index.js";
2
+ export { default as Footer } from "./layout/Footer/index.js";
3
+ export { default as Paginator } from "./Paginator/index.js";
4
+ export { default as PostCard } from "./PostCard/index.js";
5
+ export { Breadcrumbs } from "./Breadcrumbs/index.js";
6
+ export { JsonLd } from "./JsonLd.js";
@@ -1,11 +1,11 @@
1
- import type { LogoProps } from "../types";
1
+ import type { LogoProps } from "../types.js";
2
2
  export declare const dynamic = "force-static";
3
3
  export declare const revalidate = 3600;
4
4
  type FooterProps = {
5
- menuId: string;
6
- wpApiUrl: string;
7
- wpUsername: string;
8
- wpAppPassword: string;
5
+ menuId?: string;
6
+ wpApiUrl?: string;
7
+ wpUsername?: string;
8
+ wpAppPassword?: string;
9
9
  siteName: string;
10
10
  locale?: string;
11
11
  logo?: LogoProps;