gatsby-matrix-theme 53.28.5 → 53.28.7

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 CHANGED
@@ -1,3 +1,24 @@
1
+ ## [53.28.7](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/compare/v53.28.6...v53.28.7) (2026-09-01)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * compose critical-css prefix exactly like gatsby getPublicPath ([04bb5d2](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/commit/04bb5d2635a6e8ea8f5640b3513f089484d91a36))
7
+ * honor assetPrefix in critical-css links (subfolder-served sites 404 on root-relative hrefs) ([b0ed7ae](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/commit/b0ed7ae79877d237703b8a2fc57aaac12b46620b))
8
+ * update game card ([ee9248e](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/commit/ee9248ecc94ef6cf924ec155deca4d988d1951ba))
9
+ * update operator details so the link on image is conditional ([b767875](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/commit/b76787584823fba703d7a2d7f862611e01a712dc))
10
+
11
+
12
+ * Merge branch 'en-664-remove-links-from-images' into 'master' ([1735c02](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/commit/1735c024286d1f6077d35cfac9bdf72c2ff784e2))
13
+ * Merge branch 'fix/critical-css-asset-prefix' into 'master' ([12003da](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/commit/12003da1f30a0cd9b436ff765e1a8d22e22029ed))
14
+
15
+ ## [53.28.6](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/compare/v53.28.5...v53.28.6) (2026-08-26)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * update theme ([1e126bd](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/commit/1e126bd7928de0cd82fd194136ae56765a04de54))
21
+
1
22
  ## [53.28.5](https://gitlab.com/g2m-gentoo/team-floyd/themes/matrix-theme/compare/v53.28.4...v53.28.5) (2026-08-24)
2
23
 
3
24
 
@@ -39,9 +39,13 @@ function listCssChunks(publicDir) {
39
39
  return entries.filter((e) => e.isFile() && isModuleChunk(e.name)).map((e) => e.name);
40
40
  }
41
41
 
42
- function injectCriticalCss({ publicDir, config, reporter }) {
42
+ function injectCriticalCss({ publicDir, config, reporter, assetPrefix }) {
43
43
  const log = reporter || { info() {}, warn() {} };
44
44
  const minLen = config && Number.isInteger(config.minClassLen) ? config.minClassLen : 5;
45
+ // Combined asset/path prefix of the build (e.g. https://www.meutimao.com.br/apostas). Subfolder-
46
+ // served sites (partnerships) load assets from there — a root-relative href 404s on the host
47
+ // domain. Root-served sites pass '' and keep root-relative links.
48
+ const prefix = typeof assetPrefix === 'string' ? assetPrefix.replace(/\/+$/, '') : '';
45
49
 
46
50
  const chunkFiles = listCssChunks(publicDir);
47
51
  if (!chunkFiles.length) {
@@ -132,10 +136,18 @@ function injectCriticalCss({ publicDir, config, reporter }) {
132
136
  let add = '';
133
137
  for (const f of needed) {
134
138
  // skip chunks already inlined by the core theme (data-href, e.g. the base chunk) or
135
- // already linked (href) — idempotent, avoids double-loading.
136
- // eslint-disable-next-line no-continue
137
- if (html.includes(`data-href="/${f}"`) || html.includes(`href="/${f}"`)) continue;
138
- add += `<link rel="stylesheet" href="/${f}" data-crit="${f}">`;
139
+ // already linked (href) — idempotent, avoids double-loading. Check both the prefixed and
140
+ // root-relative forms: the core theme's inlined data-href carries the prefix on prefixed
141
+ // builds, while root-served builds emit root-relative everywhere.
142
+ if (
143
+ html.includes(`data-href="${prefix}/${f}"`) ||
144
+ html.includes(`href="${prefix}/${f}"`) ||
145
+ html.includes(`data-href="/${f}"`) ||
146
+ html.includes(`href="/${f}"`)
147
+ )
148
+ // eslint-disable-next-line no-continue
149
+ continue;
150
+ add += `<link rel="stylesheet" href="${prefix}/${f}" data-crit="${f}">`;
139
151
  totalLinked += 1;
140
152
  }
141
153
  // eslint-disable-next-line no-continue
@@ -111,6 +111,47 @@ describe('injectCriticalCss (integration over a temp public/)', () => {
111
111
  expect(read('index.html')).toBe(original);
112
112
  });
113
113
 
114
+ const runPrefixed = (assetPrefix) =>
115
+ injectCriticalCss({
116
+ publicDir: dir,
117
+ config: { enabled: true, skipRoutes: ['preview'], minClassLen: 5 },
118
+ reporter: silent,
119
+ assetPrefix,
120
+ });
121
+
122
+ test('prefixes hrefs with assetPrefix on subfolder-served builds', () => {
123
+ write('page-data/index/page-data.json', pageData());
124
+ write('index.html', html('<div class="Bonus_wrap__x1">x</div>'));
125
+ runPrefixed('https://www.meutimao.com.br/apostas/'); // trailing slash must be normalized
126
+ const out = read('index.html');
127
+ expect(out).toContain(
128
+ '<link rel="stylesheet" href="https://www.meutimao.com.br/apostas/100.aaa.css" data-crit="100.aaa.css">',
129
+ );
130
+ });
131
+
132
+ test('prefixed: does not double-link a chunk inlined with a prefixed data-href', () => {
133
+ write('page-data/index/page-data.json', pageData());
134
+ write(
135
+ 'index.html',
136
+ html('<div class="Bonus_wrap__x1">x</div>').replace(
137
+ '<title>t</title>',
138
+ '<title>t</title><style data-href="https://www.meutimao.com.br/apostas/100.aaa.css">.Bonus_wrap__x1{}</style>',
139
+ ),
140
+ );
141
+ runPrefixed('https://www.meutimao.com.br/apostas');
142
+ expect(read('index.html')).not.toContain('data-crit="100.aaa.css"');
143
+ });
144
+
145
+ test('prefixed: is idempotent across runs', () => {
146
+ write('page-data/index/page-data.json', pageData());
147
+ write('index.html', html('<div class="Bonus_wrap__x1 Toplist_row__y2">x</div>'));
148
+ runPrefixed('https://www.meutimao.com.br/apostas');
149
+ runPrefixed('https://www.meutimao.com.br/apostas');
150
+ const out = read('index.html');
151
+ expect(out.match(/data-crit="100\.aaa\.css"/g)).toHaveLength(1);
152
+ expect(out.match(/data-crit="200\.bbb\.css"/g)).toHaveLength(1);
153
+ });
154
+
114
155
  test('guards: missing public dir does not throw', () => {
115
156
  expect(() =>
116
157
  injectCriticalCss({ publicDir: path.join(dir, 'nope'), config: { enabled: true }, reporter: silent }),
@@ -0,0 +1,28 @@
1
+ /**
2
+ * composePublicPrefix — the combined prefix a build's asset URLs carry, replicating Gatsby's own
3
+ * getPublicPath algorithm (gatsby/dist/utils/get-public-path.js, the source of __PATH_PREFIX__ and
4
+ * webpack publicPath). Kept as a copy rather than requiring the private Gatsby path, but must stay
5
+ * in sync with it:
6
+ * - only active when the build ran with --prefix-paths and a prefix is configured
7
+ * - each part is trimmed of ONE leading and ONE trailing slash (Gatsby's exact regex — this is
8
+ * what keeps a protocol-relative `//cdn...` prefix working), empty parts dropped, joined by '/'
9
+ * - a result that is not a URL (http(s):// or protocol-relative //) gets a forced leading slash
10
+ * Returns '' (root-served) or a prefix with no trailing slash, safe to use as `${prefix}/${file}`.
11
+ */
12
+
13
+ const trimSlashes = (part) => part.replace(/(^\/)|(\/$)/g, '');
14
+ const isURL = (possibleUrl) =>
15
+ ['http://', 'https://', '//'].some((expr) => possibleUrl.startsWith(expr));
16
+
17
+ function composePublicPrefix({ assetPrefix, pathPrefix, prefixPaths }) {
18
+ if (prefixPaths && (assetPrefix || pathPrefix)) {
19
+ const normalized = [assetPrefix, pathPrefix]
20
+ .filter((part) => (part ? part.length > 0 : false))
21
+ .map((part) => trimSlashes(part))
22
+ .join('/');
23
+ return isURL(normalized) ? normalized : `/${normalized}`;
24
+ }
25
+ return '';
26
+ }
27
+
28
+ module.exports = { composePublicPrefix };
@@ -0,0 +1,45 @@
1
+ import { composePublicPrefix } from './publicPrefix';
2
+
3
+ // Mirrors Gatsby's getPublicPath (gatsby/dist/utils/get-public-path.js) — these cases are the
4
+ // documented semantics of __PATH_PREFIX__ / webpack publicPath.
5
+ describe('composePublicPrefix', () => {
6
+ test('returns "" when prefixPaths is off, regardless of config', () => {
7
+ expect(
8
+ composePublicPrefix({ assetPrefix: 'https://cdn.example.com', pathPrefix: '/sub', prefixPaths: false }),
9
+ ).toBe('');
10
+ });
11
+
12
+ test('returns "" when nothing is configured', () => {
13
+ expect(composePublicPrefix({ assetPrefix: undefined, pathPrefix: undefined, prefixPaths: true })).toBe('');
14
+ expect(composePublicPrefix({ assetPrefix: '', pathPrefix: '', prefixPaths: true })).toBe('');
15
+ });
16
+
17
+ test('URL assetPrefix: trailing slash trimmed, no leading slash forced', () => {
18
+ expect(
19
+ composePublicPrefix({ assetPrefix: 'https://www.meutimao.com.br/apostas/', prefixPaths: true }),
20
+ ).toBe('https://www.meutimao.com.br/apostas');
21
+ });
22
+
23
+ test('protocol-relative assetPrefix keeps its form', () => {
24
+ expect(composePublicPrefix({ assetPrefix: '//cdn.example.com/', prefixPaths: true })).toBe(
25
+ '//cdn.example.com',
26
+ );
27
+ });
28
+
29
+ test('pathPrefix only: leading slash forced, trailing trimmed', () => {
30
+ expect(composePublicPrefix({ pathPrefix: '/blog/', prefixPaths: true })).toBe('/blog');
31
+ expect(composePublicPrefix({ pathPrefix: 'blog', prefixPaths: true })).toBe('/blog');
32
+ });
33
+
34
+ test('assetPrefix + pathPrefix joined with a single slash', () => {
35
+ expect(
36
+ composePublicPrefix({ assetPrefix: 'https://cdn.example.com/', pathPrefix: '/blog/', prefixPaths: true }),
37
+ ).toBe('https://cdn.example.com/blog');
38
+ });
39
+
40
+ test('non-URL assetPrefix gets a forced leading slash (Gatsby getPublicPath parity)', () => {
41
+ expect(composePublicPrefix({ assetPrefix: 'cdn.example.com', prefixPaths: true })).toBe(
42
+ '/cdn.example.com',
43
+ );
44
+ });
45
+ });
package/gatsby-node.js CHANGED
@@ -21,6 +21,7 @@
21
21
  const path = require('path');
22
22
  const { resolveConfig } = require('./critical-css/config');
23
23
  const { injectCriticalCss } = require('./critical-css/injectCriticalCss');
24
+ const { composePublicPrefix } = require('./critical-css/publicPrefix');
24
25
  const { resolveConfig: resolveWidgetHeightsConfig } = require('./widget-heights/config');
25
26
  const { measureHeights, closeSharedBrowser } = require('./widget-heights/measureHeights');
26
27
  const { applyWidgetHeights } = require('./widget-heights/applyWidgetHeights');
@@ -65,10 +66,18 @@ exports.onPostBuild = async ({ reporter, store }, pluginOptions) => {
65
66
  const cfg = resolveConfig(pluginOptions);
66
67
  if (!cfg.enabled) return;
67
68
  try {
68
- const dir =
69
- (store && store.getState && store.getState().program && store.getState().program.directory) ||
70
- process.cwd();
71
- injectCriticalCss({ publicDir: path.join(dir, 'public'), config: cfg, reporter });
69
+ const state = (store && store.getState && store.getState()) || {};
70
+ const dir = (state.program && state.program.directory) || process.cwd();
71
+ // Combined prefix the build's asset URLs carry (gatsby build --prefix-paths): assetPrefix +
72
+ // pathPrefix, composed like Gatsby's own getPublicPath (see ./critical-css/publicPrefix).
73
+ // Subfolder-served sites (assetPrefix e.g. https://www.meutimao.com.br/apostas/) 404 on
74
+ // root-relative links.
75
+ const assetPrefix = composePublicPrefix({
76
+ assetPrefix: state.config && state.config.assetPrefix,
77
+ pathPrefix: state.config && state.config.pathPrefix,
78
+ prefixPaths: Boolean(state.program && state.program.prefixPaths),
79
+ });
80
+ injectCriticalCss({ publicDir: path.join(dir, 'public'), config: cfg, reporter, assetPrefix });
72
81
  } catch (e) {
73
82
  reporter.warn(`[critical-css] onPostBuild skipped: ${e && e.message}`);
74
83
  }
package/gatsby-ssr.js CHANGED
@@ -48,8 +48,9 @@ function resolvePublicDir() {
48
48
  return null;
49
49
  }
50
50
 
51
- function getModuleCssLinks() {
52
- // only cache a non-empty success; retry on failure (dir may not be resolvable on an early call)
51
+ function getModuleCssLinks(prefix) {
52
+ // only cache a non-empty success; retry on failure (dir may not be resolvable on an early call).
53
+ // prefix is constant for the life of a build/server process, so the cache stays valid.
53
54
  if (cachedLinks && cachedLinks.length) return cachedLinks;
54
55
  try {
55
56
  const dir = resolvePublicDir();
@@ -59,7 +60,7 @@ function getModuleCssLinks() {
59
60
  React.createElement('link', {
60
61
  key: f,
61
62
  rel: 'stylesheet',
62
- href: `/${f}`,
63
+ href: `${prefix}/${f}`,
63
64
  'data-crit-ssr': f,
64
65
  })
65
66
  );
@@ -78,13 +79,16 @@ function firstSegment(pathname) {
78
79
  );
79
80
  }
80
81
 
81
- exports.onRenderBody = ({ setHeadComponents, pathname }, pluginOptions) => {
82
+ exports.onRenderBody = ({ setHeadComponents, pathname, pathPrefix }, pluginOptions) => {
82
83
  try {
83
84
  const cfg = resolveConfig(pluginOptions);
84
85
  if (!cfg.enabled) return;
85
86
  if (!cfg.skipRoutes.includes(firstSegment(pathname))) return;
86
87
 
87
- const links = getModuleCssLinks();
88
+ // pathPrefix here is Gatsby's combined __PATH_PREFIX__ (assetPrefix + pathPrefix) on
89
+ // --prefix-paths builds — required for subfolder-served sites, '' on root-served ones.
90
+ const prefix = typeof pathPrefix === 'string' ? pathPrefix.replace(/\/+$/, '') : '';
91
+ const links = getModuleCssLinks(prefix);
88
92
  if (links.length) setHeadComponents(links);
89
93
  } catch (e) {
90
94
  /* never break SSR over a CSS optimisation */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gatsby-matrix-theme",
3
- "version": "53.28.5",
3
+ "version": "53.28.7",
4
4
  "main": "index.js",
5
5
  "description": "Matrix Theme NPM Package",
6
6
  "author": "",
@@ -26,7 +26,7 @@
26
26
  "@gigmedia/enigma-utils": "^1.20.0",
27
27
  "@react-icons/all-files": "^4.1.0",
28
28
  "gatsby": "^5.11.0",
29
- "gatsby-core-theme": "44.35.8",
29
+ "gatsby-core-theme": "44.35.9",
30
30
  "gatsby-plugin-sharp": "^5.11.0",
31
31
  "gatsby-plugin-sitemap": "^6.13.1",
32
32
  "gatsby-transformer-sharp": "^5.11.0",
@@ -25,6 +25,7 @@ const TemplateOne = ({
25
25
  modulePosition,
26
26
  itemPosition,
27
27
  moduleStyle,
28
+ showImageAsLink = true,
28
29
  }) => {
29
30
  const { relation, path, banner } = item;
30
31
  const { name } = relation || {};
@@ -35,26 +36,45 @@ const TemplateOne = ({
35
36
  const gameImage = relation?.logo?.filename || banner;
36
37
 
37
38
  return (
38
- <div className={`${styles?.baseCard || ''} ${featured ? styles.featured || '' : ''} ${moduleStyle ? styles[moduleStyle] || '' : ''}`}>
39
- <Link
40
- to={path}
41
- className={`game-card-gtm ${styles?.cardBanner || ''}`}
42
- aria-label={useTranslate(
43
- `ariaLabel-${name || item?.title}Link`,
44
- `${name || item?.title} Link`
45
- )}
46
- >
47
- {storybookImage || gameImage ? (
48
- <LazyImage
49
- width={width}
50
- height={height}
51
- src={storybookImage || imagePrettyUrl(gameImage, width, height)}
52
- alt={getAltText(relation?.logo, name || item?.title)}
53
- />
54
- ) : (
55
- <GatsbyImg filename="default-slot.jpg" alt={name || item?.title} />
56
- )}
57
- </Link>
39
+ <div
40
+ className={`${styles?.baseCard || ''} ${featured ? styles.featured || '' : ''} ${
41
+ moduleStyle ? styles[moduleStyle] || '' : ''
42
+ }`}
43
+ >
44
+ {showImageAsLink ? (
45
+ <Link
46
+ to={path}
47
+ className={`game-card-gtm ${styles?.cardBanner || ''}`}
48
+ aria-label={useTranslate(
49
+ `ariaLabel-${name || item?.title}Link`,
50
+ `${name || item?.title} Link`
51
+ )}
52
+ >
53
+ {storybookImage || gameImage ? (
54
+ <LazyImage
55
+ width={width}
56
+ height={height}
57
+ src={storybookImage || imagePrettyUrl(gameImage, width, height)}
58
+ alt={getAltText(relation?.logo, name || item?.title)}
59
+ />
60
+ ) : (
61
+ <GatsbyImg filename="default-slot.jpg" alt={name || item?.title} />
62
+ )}
63
+ </Link>
64
+ ) : (
65
+ <>
66
+ {storybookImage || gameImage ? (
67
+ <LazyImage
68
+ width={width}
69
+ height={height}
70
+ src={storybookImage || imagePrettyUrl(gameImage, width, height)}
71
+ alt={getAltText(relation?.logo, name || item?.title)}
72
+ />
73
+ ) : (
74
+ <GatsbyImg filename="default-slot.jpg" alt={name || item?.title} />
75
+ )}
76
+ </>
77
+ )}
58
78
  <div className={`${styles?.cardContent || ''} ${featured ? styles?.featured || '' : ''}`}>
59
79
  <Link to={path} className="game-card-gtm">
60
80
  <span className={styles?.cardTitle || ''}>{name || item?.title}</span>
@@ -165,6 +185,7 @@ TemplateOne.propTypes = {
165
185
  modulePosition: PropTypes.number,
166
186
  itemPosition: PropTypes.number,
167
187
  moduleStyle: PropTypes.string,
188
+ showImageAsLink: PropTypes.bool
168
189
  };
169
190
 
170
191
  export default TemplateOne;
@@ -53,6 +53,7 @@ const OperatorDetails = ({
53
53
  showVerificationBadge = false,
54
54
  verificationBadgeByName = false,
55
55
  reviewPathProp = null,
56
+ showImageAsLink= true
56
57
  }) => {
57
58
  const itemName = item?.name || item?.relation?.name;
58
59
  const status = item?.status || item?.relation?.status;
@@ -84,35 +85,44 @@ const OperatorDetails = ({
84
85
  </Link>
85
86
  );
86
87
 
88
+ const logoContent = (
89
+ <>
90
+ <LazyImage
91
+ src={imagePrettyUrl(image?.filename, imageWidth, imageHeight)}
92
+ alt={getAltText(image, itemName)}
93
+ width={imageWidth}
94
+ height={imageHeight}
95
+ className={styles.image}
96
+ loading={imageLoad}
97
+ />
98
+
99
+ {showRibbon &&
100
+ !contentRibbon &&
101
+ (status === 'active'
102
+ ? hasRibbons && (
103
+ <Ribbons
104
+ item={[ribbons[0]]}
105
+ customStyle={`${styles.ribbon} ${contentRibbon && styles.contentRibbon}`}
106
+ />
107
+ )
108
+ : showNonActiveRibbons && (
109
+ <Ribbons
110
+ item={[useTranslate(`${status}_ribbon`, ribbonText[`${status}_ribbon`])]}
111
+ customStyle={`${styles.ribbon} ${contentRibbon && styles.contentRibbon} ${
112
+ styles[status] || ''
113
+ }`}
114
+ />
115
+ ))}
116
+ </>
117
+ );
118
+
87
119
  return (
88
120
  <div className={`${styles.operatorDetails} ${costumeStyle}`}>
89
- <Tag classStyle="logo-cta-gtm">
90
- <LazyImage
91
- src={imagePrettyUrl(image?.filename, imageWidth, imageHeight)}
92
- alt={getAltText(image, itemName)}
93
- width={imageWidth}
94
- height={imageHeight}
95
- className={styles.image}
96
- loading={imageLoad}
97
- />
98
- {showRibbon &&
99
- !contentRibbon &&
100
- (status === 'active'
101
- ? hasRibbons && (
102
- <Ribbons
103
- item={[ribbons[0]]}
104
- customStyle={`${styles.ribbon} ${contentRibbon && styles.contentRibbon}`}
105
- />
106
- )
107
- : showNonActiveRibbons && (
108
- <Ribbons
109
- item={[useTranslate(`${status}_ribbon`, ribbonText[`${status}_ribbon`])]}
110
- customStyle={`${styles.ribbon} ${contentRibbon && styles.contentRibbon} ${
111
- styles[status] || ''
112
- }`}
113
- />
114
- ))}
115
- </Tag>
121
+ {showImageAsLink ? (
122
+ <Tag classStyle="logo-cta-gtm">{logoContent}</Tag>
123
+ ) : (
124
+ <div className={styles.logoContent}>{logoContent}</div>
125
+ )}
116
126
 
117
127
  <div className={styles.details}>
118
128
  {showRibbon &&
@@ -253,6 +263,7 @@ OperatorDetails.propTypes = {
253
263
  showVerificationBadge: PropTypes.bool,
254
264
  verificationBadgeByName: PropTypes.bool,
255
265
  reviewPathProp: PropTypes.string,
266
+ showImageAsLink: PropTypes.bool
256
267
  };
257
268
 
258
269
  export default OperatorDetails;