@autobusal/common 1.4.2 → 1.4.4

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.
@@ -1,5 +1,6 @@
1
1
  import { TFunction } from 'i18next';
2
2
  import { FiCalendar } from 'react-icons/fi';
3
+ import { sanitizeHtml } from '@autobusal/utilities';
3
4
  import Image from './Image';
4
5
  import { LinkTitle, Details, DisplayDate, TextPreview, TextView, ButtonLink } from './styles';
5
6
  import { ArticleData } from '@autobusal/providers/types/articles';
@@ -33,7 +34,7 @@ const BlogItem = ({ article, type, t }: Props): JSX.Element => (
33
34
  </TextPreview>
34
35
  ) }
35
36
 
36
- { type === 'view' && <TextView dangerouslySetInnerHTML={{ __html: article.content }} /> }
37
+ { type === 'view' && <TextView dangerouslySetInnerHTML={{ __html: sanitizeHtml(article.content) }} /> }
37
38
  </div>
38
39
  );
39
40
 
package/CHANGELOG.md CHANGED
@@ -3,6 +3,28 @@
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.4.4] - 2026-07-24
7
+
8
+ ### Fixed
9
+
10
+ - `BlogItem.tsx` and `Policy.tsx`: article/policy content is now run through `@autobusal/utilities`'s `sanitizeHtml` before being rendered via `dangerouslySetInnerHTML`, closing an XSS gap where an already-compromised admin account could persist JS in blog articles or policy pages.
11
+
12
+ ## [1.4.3] - 2026-07-19
13
+
14
+ ### Changed
15
+
16
+ - **`Meta` (`Meta.tsx`) is now brand-configurable, eliminating the per-brand SEO fork.**
17
+ Merged magus's rich SEO `Meta` (robots, canonical, Open Graph and Twitter card tags, plus
18
+ optional `image`/`url`/`type`/`noIndex` props) into the shared component, and replaced the
19
+ hard-coded "BusMagus" strings with a `VITE_APP_NAME` build-time env: the `<title>` suffix,
20
+ `og:title`/`twitter:title` and `og:site_name` derive from that brand name, and when it is
21
+ unset the title renders bare (no suffix) with `og:site_name` omitted — so a brand that has
22
+ not configured a name is unaffected. This lets every whitelabel consume the published
23
+ `Meta` and pass its own brand via env, instead of magus vite-aliasing `@autobusal/common`
24
+ to a local `src/modules/Common` copy just to override this one file. `children` is now
25
+ optional; the prop set is a superset of the previous one, so all existing `<Meta title=…>`
26
+ call sites are unaffected.
27
+
6
28
  ## [1.4.2] - 2026-07-19
7
29
 
8
30
  ### Added
package/Meta.tsx CHANGED
@@ -4,20 +4,53 @@ interface Props {
4
4
  title: string
5
5
  keywords?: string
6
6
  description?: string
7
- children: any
7
+ image?: string
8
+ url?: string
9
+ type?: string
10
+ noIndex?: boolean
11
+ children?: any
8
12
  }
9
13
 
10
- const Meta = ({ title, keywords, description, children }: Props): JSX.Element => (
14
+ // Brand display name for SEO, set per whitelabel via VITE_APP_NAME (build-time
15
+ // Vite env). It drives the <title> suffix, the og/twitter titles and
16
+ // og:site_name. When unset, titles render bare (no suffix) and og:site_name is
17
+ // omitted, so a brand that has not configured a name is unaffected. This is
18
+ // what lets every brand consume the published @autobusal/common Meta instead of
19
+ // aliasing a per-brand fork.
20
+ const brand = import.meta.env.VITE_APP_NAME as string | undefined;
21
+
22
+ const withBrand = (value: string): string => (brand ? `${ value } - ${ brand }` : value);
23
+
24
+ const Meta = ({ title, keywords, description, image, url, type = 'website', noIndex = false, children }: Props): JSX.Element => (
11
25
  <>
12
26
  <Helmet>
13
- <title>{ title }</title>
27
+ <title>{ withBrand(title) }</title>
28
+
29
+ {/* Robots */}
30
+ <meta name="robots" content={ noIndex ? 'noindex, nofollow' : 'index, follow' } />
14
31
 
32
+ {/* Standard Meta Tags */}
15
33
  { keywords && <meta name="keywords" content={ keywords } /> }
16
34
  { description && <meta name="description" content={ description } /> }
35
+ { url && <link rel="canonical" href={ url } /> }
36
+
37
+ {/* Open Graph / Facebook */}
38
+ <meta property="og:type" content={ type } />
39
+ <meta property="og:title" content={ withBrand(title) } />
40
+ { description && <meta property="og:description" content={ description } /> }
41
+ { image && <meta property="og:image" content={ image } /> }
42
+ { url && <meta property="og:url" content={ url } /> }
43
+ { brand && <meta property="og:site_name" content={ brand } /> }
44
+
45
+ {/* Twitter */}
46
+ <meta name="twitter:card" content="summary_large_image" />
47
+ <meta name="twitter:title" content={ withBrand(title) } />
48
+ { description && <meta name="twitter:description" content={ description } /> }
49
+ { image && <meta name="twitter:image" content={ image } /> }
17
50
  </Helmet>
18
51
 
19
52
  { children }
20
53
  </>
21
54
  );
22
55
 
23
- export default Meta;
56
+ export default Meta;
package/Policy/Policy.tsx CHANGED
@@ -1,4 +1,5 @@
1
1
  import { TFunction } from 'i18next';
2
+ import { sanitizeHtml } from '@autobusal/utilities';
2
3
  import Modal from '../Modal/Modal';
3
4
  import { useGetPolicy } from './services';
4
5
 
@@ -17,7 +18,7 @@ const Policy = ({ id, t, onClose }: Props): JSX.Element => {
17
18
  width={ 750 }
18
19
  title={ t('policy.title') }
19
20
  content={
20
- <div dangerouslySetInnerHTML={{ __html: data?.policies ?? '' }} />
21
+ <div dangerouslySetInnerHTML={{ __html: sanitizeHtml(data?.policies) }} />
21
22
  }
22
23
  onClose={ onClose }
23
24
  />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autobusal/common",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "author": "Ferjolt Ozuni",
5
5
  "type": "module",
6
6
  "main": "index.ts"