gatsby-core-theme 44.0.41 → 44.1.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/CHANGELOG.md +23 -0
- package/package.json +1 -1
- package/src/components/organisms/head/index.js +2 -2
- package/src/components/organisms/navigation/index.js +6 -8
- package/src/components/organisms/navigation/navigation.test.js +68 -25
- package/src/constants/metaTags.js +71 -15
- package/src/helpers/head.js +48 -8
- package/src/helpers/head.test.js +26 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
# [44.1.0](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.0.42...v44.1.0) (2025-05-21)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
* Merge branch 'tm-5470-custom-logo-alt' into 'master' ([51d98bb](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/51d98bb106549c47f61540780a5efd592202b67e))
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* custom logo alt ([ddf1164](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/ddf1164ea20a2143dff63a97fff5083293b9bcb8))
|
|
10
|
+
|
|
11
|
+
## [44.0.42](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.0.41...v44.0.42) (2025-05-21)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* fix test ([033c59d](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/033c59d02855f46fe2b484b1927e9d94c81c28d2))
|
|
17
|
+
* make changes ([0155c8c](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/0155c8c074b0b51b2926d0a1963ffa26db3401c8))
|
|
18
|
+
* remove static logic for IRL ([d51dd66](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/d51dd66f4ef558432b5095940f21a01381e4daa9))
|
|
19
|
+
* remove when content is null ([7ed4f5d](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/7ed4f5daacbe07658ada459dce15abb6394e5e34))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
* Merge branch 'tm-5213-head-update' into 'master' ([28abae7](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/commit/28abae7bdf0a46f1e8ac05c06dc6a6914ae4f665))
|
|
23
|
+
|
|
1
24
|
## [44.0.41](https://gitlab.com/g2m-gentoo/team-floyd/themes/gatsby-themes/compare/v44.0.40...v44.0.41) (2025-05-20)
|
|
2
25
|
|
|
3
26
|
|
package/package.json
CHANGED
|
@@ -7,9 +7,9 @@ import { getUrl, getLanguage } from "~helpers/getters";
|
|
|
7
7
|
import { getMetaTags, getCanonicalUrl } from "~helpers/head";
|
|
8
8
|
import customData from "./customData";
|
|
9
9
|
|
|
10
|
-
const HeadData = ({ page = {}
|
|
10
|
+
const HeadData = ({ page = {} }) => {
|
|
11
11
|
const isTracker = page.template === "tracker";
|
|
12
|
-
const metaTags = getMetaTags(page,
|
|
12
|
+
const metaTags = getMetaTags(page, isTracker);
|
|
13
13
|
let defaultHref = null;
|
|
14
14
|
|
|
15
15
|
return (
|
|
@@ -26,6 +26,7 @@ const Navigation = ({
|
|
|
26
26
|
stopScrollOnOpen = true,
|
|
27
27
|
canOpenAllSubMenus = true,
|
|
28
28
|
logo = "/images/logo.svg",
|
|
29
|
+
logoAlt = `${process.env.GATSBY_SITE_NAME} logo`,
|
|
29
30
|
logoWidth = 200,
|
|
30
31
|
logoHeight = 31,
|
|
31
32
|
searchIcon = null,
|
|
@@ -39,7 +40,6 @@ const Navigation = ({
|
|
|
39
40
|
megaMenu = false,
|
|
40
41
|
menu,
|
|
41
42
|
}) => {
|
|
42
|
-
|
|
43
43
|
const navRef = useRef(React.createRef());
|
|
44
44
|
const { admin } = useContext(Context) || {};
|
|
45
45
|
const showMenu =
|
|
@@ -54,12 +54,7 @@ const Navigation = ({
|
|
|
54
54
|
pageTypes[template]?.showLogoWithLink ?? pageTypes.default.showLogoWithLink;
|
|
55
55
|
|
|
56
56
|
const logoImg = (
|
|
57
|
-
<img
|
|
58
|
-
alt={`${process.env.GATSBY_SITE_NAME} logo`}
|
|
59
|
-
src={logo}
|
|
60
|
-
width={logoWidth}
|
|
61
|
-
height={logoHeight}
|
|
62
|
-
/>
|
|
57
|
+
<img alt={logoAlt} src={logo} width={logoWidth} height={logoHeight} />
|
|
63
58
|
);
|
|
64
59
|
|
|
65
60
|
if (stopScrollOnOpen) toggleScroll("", true);
|
|
@@ -135,7 +130,9 @@ const Navigation = ({
|
|
|
135
130
|
/>
|
|
136
131
|
|
|
137
132
|
<div className={styles.navIconContainer}>
|
|
138
|
-
{activeMarket && !disableMarketDropdown &&
|
|
133
|
+
{activeMarket && !disableMarketDropdown && (
|
|
134
|
+
<MarketDropdown pageContext={pageContext} />
|
|
135
|
+
)}
|
|
139
136
|
{showNotifications && <Notifications section={section} />}
|
|
140
137
|
{hasCustomComponent && (
|
|
141
138
|
<CustomComponent
|
|
@@ -205,6 +202,7 @@ Navigation.propTypes = {
|
|
|
205
202
|
megaMenu: PropTypes.bool,
|
|
206
203
|
menu: PropTypes.string,
|
|
207
204
|
logo: PropTypes.string,
|
|
205
|
+
logoAlt: PropTypes.string,
|
|
208
206
|
logoWidth: PropTypes.number,
|
|
209
207
|
logoHeight: PropTypes.number,
|
|
210
208
|
};
|
|
@@ -1,43 +1,86 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { render, cleanup, waitFor } from
|
|
3
|
-
import
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, cleanup, waitFor } from "@testing-library/react";
|
|
3
|
+
import "@testing-library/jest-dom/extend-expect";
|
|
4
4
|
|
|
5
|
-
import { getNavigationMenus } from
|
|
6
|
-
import getPageData from
|
|
7
|
-
import Navigation from
|
|
5
|
+
import { getNavigationMenus } from "~tests/factories/sections/navigation.factory";
|
|
6
|
+
import getPageData from "../../../../tests/factories/pages/default.factory";
|
|
7
|
+
import Navigation from ".";
|
|
8
8
|
|
|
9
9
|
const menuSection = getNavigationMenus(1, 2, true);
|
|
10
|
-
const pageContext = {page: getPageData()}
|
|
11
|
-
describe(
|
|
12
|
-
test(
|
|
13
|
-
const { container } = render(
|
|
10
|
+
const pageContext = { page: getPageData() };
|
|
11
|
+
describe("Navigation Component", () => {
|
|
12
|
+
test("render navigation", async () => {
|
|
13
|
+
const { container } = render(
|
|
14
|
+
<Navigation pageContext={pageContext} section={menuSection} />
|
|
15
|
+
);
|
|
14
16
|
|
|
15
17
|
await waitFor(() => {
|
|
16
|
-
expect(container.querySelectorAll(
|
|
17
|
-
expect(container.querySelectorAll(
|
|
18
|
-
expect(container.querySelectorAll(
|
|
19
|
-
expect(container.querySelectorAll(
|
|
18
|
+
expect(container.querySelectorAll(".nav")).toHaveLength(1);
|
|
19
|
+
expect(container.querySelectorAll(".logo")).toHaveLength(1);
|
|
20
|
+
expect(container.querySelectorAll(".menuContainer")).toHaveLength(1);
|
|
21
|
+
expect(container.querySelectorAll(".search")).toHaveLength(1);
|
|
20
22
|
});
|
|
21
23
|
});
|
|
22
|
-
test(
|
|
23
|
-
const { container } = render(
|
|
24
|
+
test("render navigation when template is ppc", async () => {
|
|
25
|
+
const { container } = render(
|
|
26
|
+
<Navigation
|
|
27
|
+
pageContext={pageContext}
|
|
28
|
+
section={menuSection}
|
|
29
|
+
template="ppc"
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
24
32
|
|
|
25
33
|
await waitFor(() => {
|
|
26
|
-
expect(container.querySelectorAll(
|
|
27
|
-
expect(container.querySelectorAll(
|
|
28
|
-
expect(container.querySelectorAll(
|
|
29
|
-
expect(container.querySelectorAll(
|
|
34
|
+
expect(container.querySelectorAll(".nav")).toHaveLength(1);
|
|
35
|
+
expect(container.querySelectorAll(".logo")).toHaveLength(1);
|
|
36
|
+
expect(container.querySelectorAll(".menuContainer")).toHaveLength(0);
|
|
37
|
+
expect(container.querySelectorAll(".search")).toHaveLength(0);
|
|
30
38
|
});
|
|
31
39
|
});
|
|
32
|
-
test(
|
|
33
|
-
const { container } = render(
|
|
40
|
+
test("render navigation without search", async () => {
|
|
41
|
+
const { container } = render(
|
|
42
|
+
<Navigation
|
|
43
|
+
pageContext={pageContext}
|
|
44
|
+
section={menuSection}
|
|
45
|
+
hasSearch={false}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
34
48
|
|
|
35
49
|
await waitFor(() => {
|
|
36
|
-
expect(container.querySelectorAll(
|
|
37
|
-
expect(container.querySelectorAll(
|
|
38
|
-
expect(container.querySelectorAll(
|
|
50
|
+
expect(container.querySelectorAll(".nav")).toHaveLength(1);
|
|
51
|
+
expect(container.querySelectorAll(".menuContainer")).toHaveLength(1);
|
|
52
|
+
expect(container.querySelectorAll(".search")).toHaveLength(0);
|
|
39
53
|
});
|
|
40
54
|
});
|
|
55
|
+
test("render navigation with custom logo alt", async () => {
|
|
56
|
+
const { container } = render(
|
|
57
|
+
<Navigation
|
|
58
|
+
pageContext={pageContext}
|
|
59
|
+
section={menuSection}
|
|
60
|
+
hasSearch={false}
|
|
61
|
+
logoAlt="custom logo alt"
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
expect(container.querySelectorAll("img")[0]).toHaveProperty(
|
|
66
|
+
"alt",
|
|
67
|
+
"custom logo alt"
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
test("render navigation with default logo alt", async () => {
|
|
71
|
+
const { container } = render(
|
|
72
|
+
<Navigation
|
|
73
|
+
pageContext={pageContext}
|
|
74
|
+
section={menuSection}
|
|
75
|
+
hasSearch={false}
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
expect(container.querySelectorAll("img")[0]).toHaveProperty(
|
|
80
|
+
"alt",
|
|
81
|
+
`${process.env.GATSBY_SITE_NAME} logo`
|
|
82
|
+
);
|
|
83
|
+
});
|
|
41
84
|
});
|
|
42
85
|
afterEach(() => {
|
|
43
86
|
cleanup();
|
|
@@ -1,15 +1,71 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
import parse from 'html-react-parser';
|
|
3
|
+
import { getLanguage, setName, getPageImage, imagePrettyUrl } from "~helpers/getters";
|
|
4
|
+
import { getRobotOptions, getCanonicalUrl, transformMetaTitle, getTwitterUsername } from "~helpers/head";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export default (page, isTracker) => {
|
|
9
|
+
const { relation, meta_title, meta_description, relation_type, siteInfo } = page;
|
|
10
|
+
const pageImage = getPageImage(page) || imagePrettyUrl(siteInfo?.site_logo);
|
|
11
|
+
const parsedMetaDescr = meta_description ? parse(meta_description) : '';
|
|
12
|
+
const metaTitle = transformMetaTitle(relation, meta_title, relation_type);
|
|
13
|
+
const twitterUsername = getTwitterUsername(page.siteSchema?.twitter);
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
return [
|
|
17
|
+
{ type: "meta", name: "description", content: page.meta_description },
|
|
18
|
+
{
|
|
19
|
+
type: "meta",
|
|
20
|
+
name: "robots",
|
|
21
|
+
content: getRobotOptions(page.robot_options),
|
|
22
|
+
},
|
|
23
|
+
{ type: "meta", property: "og:title", content: metaTitle},
|
|
24
|
+
{
|
|
25
|
+
type: "meta",
|
|
26
|
+
property: "og:site_name",
|
|
27
|
+
content: siteInfo?.site_name ? setName(siteInfo.site_name) : "",
|
|
28
|
+
},
|
|
29
|
+
{ type: "meta", property: "og:description", content: parsedMetaDescr },
|
|
30
|
+
{
|
|
31
|
+
type: "meta",
|
|
32
|
+
property: "og:type",
|
|
33
|
+
content: page.path === "/" ? "website" : "article",
|
|
34
|
+
},
|
|
35
|
+
{ type: "meta", property: "og:image", content: pageImage },
|
|
36
|
+
{
|
|
37
|
+
type: "meta",
|
|
38
|
+
property: "og:url",
|
|
39
|
+
content: getCanonicalUrl(page, isTracker),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
type: "meta",
|
|
43
|
+
property: "og:locale",
|
|
44
|
+
content:
|
|
45
|
+
getLanguage(page.language) === "en"
|
|
46
|
+
? "en_GB"
|
|
47
|
+
: getLanguage(page.language),
|
|
48
|
+
},
|
|
49
|
+
{ type: "meta", content: process.env.PLACENAME },
|
|
50
|
+
{ type: "region", content: process.env.COUNTRY },
|
|
51
|
+
{
|
|
52
|
+
type: "meta",
|
|
53
|
+
name: "facebook-domain-verification",
|
|
54
|
+
content: process.env.FBVERIFACTION,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "meta",
|
|
58
|
+
name: "robots",
|
|
59
|
+
content:
|
|
60
|
+
process.env.GATSBY_ACTIVE_ENV !== "development"
|
|
61
|
+
? page?.meta_robots?.join(",")
|
|
62
|
+
: null,
|
|
63
|
+
},
|
|
64
|
+
{ type: "meta", name: "twitter:title", content: twitterUsername && metaTitle },
|
|
65
|
+
{ type: "meta", name: "twitter:description", content: twitterUsername && parsedMetaDescr },
|
|
66
|
+
{ type: "meta", name: "twitter:site", content: twitterUsername && `@${twitterUsername}` },
|
|
67
|
+
{ type: "meta", name: "twitter:creator", content: twitterUsername && `@${twitterUsername}` },
|
|
68
|
+
{ type: "meta", name: "twitter:card", content: twitterUsername && 'summary' },
|
|
69
|
+
{ type: "meta", name: "twitter:image", content: twitterUsername && pageImage.replace('/filters:format(webp)', '') },
|
|
70
|
+
]
|
|
71
|
+
};
|
package/src/helpers/head.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { getPageImage, imagePrettyUrl } from "~helpers/getters";
|
|
2
|
+
import { getPageImage, imagePrettyUrl, getBonus } from "~helpers/getters";
|
|
3
|
+
import { generatePlaceholderString } from "~helpers/generators";
|
|
3
4
|
import keygen from "~helpers/keygen";
|
|
4
5
|
import metaTags from "~constants/metaTags";
|
|
5
6
|
|
|
6
7
|
export const getMetaTags = (page, siteInfo, isTracker) => {
|
|
7
8
|
const pageImage = getPageImage(page) || imagePrettyUrl(siteInfo?.site_logo);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
// eslint-disable-next-line array-callback-return
|
|
10
|
+
return metaTags(page, siteInfo, pageImage, isTracker).map((meta) => {
|
|
11
|
+
if (meta?.content) {
|
|
12
|
+
return (
|
|
13
|
+
<meta
|
|
14
|
+
key={keygen()}
|
|
15
|
+
{...(meta.name ? { name: meta.name } : { property: meta.property })}
|
|
16
|
+
content={meta.content}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
15
21
|
};
|
|
16
22
|
|
|
17
23
|
export function getCanonicalUrl(page, isTracker) {
|
|
@@ -49,3 +55,37 @@ export function getRobotOptions(options) {
|
|
|
49
55
|
array.push("noindex,follow");
|
|
50
56
|
return array.join();
|
|
51
57
|
}
|
|
58
|
+
|
|
59
|
+
export function getLocale(language) {
|
|
60
|
+
if (language) {
|
|
61
|
+
const locale = language.split("_").reverse();
|
|
62
|
+
locale[1] = locale[1].toUpperCase();
|
|
63
|
+
return locale.join("_");
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function getTwitterUsername(url) {
|
|
69
|
+
// eslint-disable-next-line no-useless-escape
|
|
70
|
+
const regex = /https?:\/\/(www\.)?twitter\.com\/(#!\/)?@?([^\/]*)/;
|
|
71
|
+
const m = regex.exec(url);
|
|
72
|
+
|
|
73
|
+
if (m !== null && m.length >= 3) {
|
|
74
|
+
return m[3];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function transformMetaTitle(relation, metaTitle, type) {
|
|
81
|
+
if (type !== "operator") return metaTitle;
|
|
82
|
+
|
|
83
|
+
switch (metaTitle) {
|
|
84
|
+
case "[OPERATOR_REVIEW_META_TITLE]":
|
|
85
|
+
return `${relation.name} ${generatePlaceholderString("[YEAR]")} ${
|
|
86
|
+
getBonus("main", relation).one_liner
|
|
87
|
+
}`;
|
|
88
|
+
default:
|
|
89
|
+
return metaTitle;
|
|
90
|
+
}
|
|
91
|
+
}
|
package/src/helpers/head.test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {getMetaTags, getCanonicalUrl} from './head';
|
|
1
|
+
import {getMetaTags, getCanonicalUrl, getTwitterUsername, getLocale} from './head';
|
|
2
2
|
|
|
3
3
|
describe('head.js functions', () => {
|
|
4
4
|
describe('getMetaTags', () => {
|
|
@@ -47,4 +47,29 @@ describe('head.js functions', () => {
|
|
|
47
47
|
expect(getCanonicalUrl(page, false)).toBe('https://example.com/about');
|
|
48
48
|
});
|
|
49
49
|
});
|
|
50
|
+
|
|
51
|
+
describe('getLocale', () => {
|
|
52
|
+
it('returns null when no language is provided', () => {
|
|
53
|
+
expect(getLocale(null)).toBeNull();
|
|
54
|
+
expect(getLocale(undefined)).toBeNull();
|
|
55
|
+
expect(getLocale('')).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('transforms language code correctly', () => {
|
|
59
|
+
expect(getLocale('en_us')).toBe('us_EN');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('getTwitterUsername', () => {
|
|
64
|
+
it('returns null for invalid Twitter URLs', () => {
|
|
65
|
+
expect(getTwitterUsername('')).toBeNull();
|
|
66
|
+
expect(getTwitterUsername('https://example.com')).toBeNull();
|
|
67
|
+
expect(getTwitterUsername('https://twitter.com')).toBeNull();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('extracts username from various Twitter URL formats', () => {
|
|
71
|
+
expect(getTwitterUsername('https://twitter.com/username')).toBe('username');
|
|
72
|
+
expect(getTwitterUsername('https://www.twitter.com/username')).toBe('username');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
50
75
|
});
|