@autobusal/common 1.4.6 → 1.5.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/BlogItem/BlogItem.tsx +6 -3
- package/BlogItem/Image.tsx +4 -3
- package/BlogItem/styles.ts +8 -0
- package/CHANGELOG.md +28 -0
- package/Meta.tsx +34 -27
- package/package.json +1 -1
package/BlogItem/BlogItem.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { TFunction } from 'i18next';
|
|
|
2
2
|
import { FiCalendar } from 'react-icons/fi';
|
|
3
3
|
import { sanitizeHtml } from '@autobusal/utilities';
|
|
4
4
|
import Image from './Image';
|
|
5
|
-
import { LinkTitle, Details, DisplayDate, TextPreview, TextView, ButtonLink } from './styles';
|
|
5
|
+
import { LinkTitle, Title, Details, DisplayDate, TextPreview, TextView, ButtonLink } from './styles';
|
|
6
6
|
import { ArticleData } from '@autobusal/providers/types/articles';
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
@@ -13,9 +13,12 @@ interface Props {
|
|
|
13
13
|
|
|
14
14
|
const BlogItem = ({ article, type, t }: Props): JSX.Element => (
|
|
15
15
|
<div className="box">
|
|
16
|
-
{ article.image_url !== null && <Image type={ type } internal={ article.internal } image_url={ article.image_url } /> }
|
|
16
|
+
{ article.image_url !== null && <Image type={ type } internal={ article.internal } image_url={ article.image_url } title={ article.title } /> }
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
{ type === 'view'
|
|
19
|
+
? <Title>{ article.title }</Title>
|
|
20
|
+
: <LinkTitle to={ `/blog/article/${ article.internal }` }>{ article.title }</LinkTitle>
|
|
21
|
+
}
|
|
19
22
|
|
|
20
23
|
<Details>
|
|
21
24
|
<DisplayDate>
|
package/BlogItem/Image.tsx
CHANGED
|
@@ -4,19 +4,20 @@ interface Props {
|
|
|
4
4
|
type: 'preview' | 'view' | 'short'
|
|
5
5
|
internal: string
|
|
6
6
|
image_url: string
|
|
7
|
+
title: string
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
const Image = ({ type, internal, image_url }: Props): JSX.Element => {
|
|
10
|
+
const Image = ({ type, internal, image_url, title }: Props): JSX.Element => {
|
|
10
11
|
if (type === 'preview' || type === 'short') {
|
|
11
12
|
return (
|
|
12
13
|
<ImageLink to={ `/blog/article/${ internal }` }>
|
|
13
|
-
<ContainerImage src={ image_url } />
|
|
14
|
+
<ContainerImage src={ image_url } alt={ title } />
|
|
14
15
|
</ImageLink>
|
|
15
16
|
);
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
return (
|
|
19
|
-
<ContainerImage src={ image_url } />
|
|
20
|
+
<ContainerImage src={ image_url } alt={ title } />
|
|
20
21
|
);
|
|
21
22
|
};
|
|
22
23
|
|
package/BlogItem/styles.ts
CHANGED
|
@@ -28,6 +28,14 @@ export const LinkTitle = styled(Link)`
|
|
|
28
28
|
}
|
|
29
29
|
`;
|
|
30
30
|
|
|
31
|
+
// Single-article view renders the title as a real <h1> instead of a
|
|
32
|
+
// self-link back to the same page - same visual weight as LinkTitle.
|
|
33
|
+
export const Title = styled.h1`
|
|
34
|
+
font-size: ${ props => props.theme.size.xl };
|
|
35
|
+
font-weight: 700;
|
|
36
|
+
margin: 0;
|
|
37
|
+
`;
|
|
38
|
+
|
|
31
39
|
export const Details = styled.div`
|
|
32
40
|
display: flex;
|
|
33
41
|
gap: 15px;
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,34 @@
|
|
|
3
3
|
All notable changes to `@autobusal/common` are documented here. This project follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/) and [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [1.5.0] - 2026-07-30
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- **`Meta.tsx` migrated off `react-helmet` to React 19's native document
|
|
11
|
+
metadata support.** react-helmet 6.1.0 (unmaintained since ~2021) was
|
|
12
|
+
discovered to be completely non-functional under React 19: zero of its DOM
|
|
13
|
+
writes were ever committing on any route, on any fresh page load, in either
|
|
14
|
+
consuming app - confirmed via the absence of `[data-react-helmet]` in the
|
|
15
|
+
DOM and by bisecting back through the app's dependency history to before
|
|
16
|
+
any of today's changes. Every page's `<title>`, `description`, `robots`,
|
|
17
|
+
`og:*`/`twitter:*` tags were silently frozen at whatever the static
|
|
18
|
+
`index.html` shipped, for every real user and JS-executing crawler landing
|
|
19
|
+
directly on a URL. `<title>`/`<meta>`/`<link>` are now rendered as plain
|
|
20
|
+
elements - React 19 auto-hoists and deduplicates them into `<head>` with no
|
|
21
|
+
library needed, and the same "deepest/last-rendered wins" semantics Helmet
|
|
22
|
+
was supposed to provide (a page's own `<Meta>` overriding
|
|
23
|
+
`@autobusal/providers`'s app-shell fallback title) now actually work.
|
|
24
|
+
|
|
25
|
+
## [1.4.7] - 2026-07-30
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **Blog thumbnails missing `alt` text (`BlogItem/Image.tsx`).** Neither the
|
|
30
|
+
preview/short grid thumbnail nor the full article image had `alt` - added a
|
|
31
|
+
required `title` prop (threaded through from `BlogItem.tsx`'s
|
|
32
|
+
`article.title`) used as the `alt` text on both.
|
|
33
|
+
|
|
6
34
|
## [1.4.6] - 2026-07-29
|
|
7
35
|
|
|
8
36
|
### Fixed
|
package/Meta.tsx
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { Helmet } from 'react-helmet';
|
|
2
|
-
|
|
3
1
|
interface Props {
|
|
4
2
|
title: string
|
|
5
3
|
keywords?: string
|
|
@@ -21,33 +19,42 @@ const brand = import.meta.env.VITE_APP_NAME as string | undefined;
|
|
|
21
19
|
|
|
22
20
|
const withBrand = (value: string): string => (brand ? `${ value } - ${ brand }` : value);
|
|
23
21
|
|
|
22
|
+
// React 19 automatically hoists any <title>/<meta>/<link> rendered ANYWHERE
|
|
23
|
+
// in the component tree into <head>, deduplicating <title> and meta[name=...]
|
|
24
|
+
// tags (last-rendered wins) - no wrapper component needed. This replaced
|
|
25
|
+
// react-helmet (6.1.0, unmaintained since ~2021), which had gone completely
|
|
26
|
+
// non-functional under React 19: none of its DOM writes were ever committing
|
|
27
|
+
// (verified: zero [data-react-helmet] tags in the DOM on any route, on any
|
|
28
|
+
// page load, even before this session's changes). Since Preload.tsx (this
|
|
29
|
+
// package's sibling app-shell fallback) renders its own <title> higher in the
|
|
30
|
+
// tree, React's last-wins dedup means whichever page's <Meta> renders here -
|
|
31
|
+
// deeper in the tree, so later in render order - correctly overrides it, the
|
|
32
|
+
// same behavior Helmet was supposed to provide but silently didn't.
|
|
24
33
|
const Meta = ({ title, keywords, description, image, url, type = 'website', noIndex = false, children }: Props): JSX.Element => (
|
|
25
34
|
<>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
{ image && <meta name="twitter:image" content={ image } /> }
|
|
50
|
-
</Helmet>
|
|
35
|
+
<title>{ withBrand(title) }</title>
|
|
36
|
+
|
|
37
|
+
{/* Robots */}
|
|
38
|
+
<meta name="robots" content={ noIndex ? 'noindex, nofollow' : 'index, follow' } />
|
|
39
|
+
|
|
40
|
+
{/* Standard Meta Tags */}
|
|
41
|
+
{ keywords && <meta name="keywords" content={ keywords } /> }
|
|
42
|
+
{ description && <meta name="description" content={ description } /> }
|
|
43
|
+
{ url && <link rel="canonical" href={ url } /> }
|
|
44
|
+
|
|
45
|
+
{/* Open Graph / Facebook */}
|
|
46
|
+
<meta property="og:type" content={ type } />
|
|
47
|
+
<meta property="og:title" content={ withBrand(title) } />
|
|
48
|
+
{ description && <meta property="og:description" content={ description } /> }
|
|
49
|
+
{ image && <meta property="og:image" content={ image } /> }
|
|
50
|
+
{ url && <meta property="og:url" content={ url } /> }
|
|
51
|
+
{ brand && <meta property="og:site_name" content={ brand } /> }
|
|
52
|
+
|
|
53
|
+
{/* Twitter */}
|
|
54
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
55
|
+
<meta name="twitter:title" content={ withBrand(title) } />
|
|
56
|
+
{ description && <meta name="twitter:description" content={ description } /> }
|
|
57
|
+
{ image && <meta name="twitter:image" content={ image } /> }
|
|
51
58
|
|
|
52
59
|
{ children }
|
|
53
60
|
</>
|