gatsby-theme-q3 3.1.5 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -3,74 +3,86 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [3.1.5](https://github.com/3merge/q/compare/v3.1.4...v3.1.5) (2022-02-01)
6
+ # [3.2.0](https://github.com/3merge/q/compare/v3.1.5...v3.2.0) (2022-02-09)
7
7
 
8
- **Note:** Version bump only for package gatsby-theme-q3
9
-
10
-
11
-
12
-
13
-
14
- ## [3.1.4](https://github.com/3merge/q/compare/v3.1.3...v3.1.4) (2022-02-01)
15
-
16
- **Note:** Version bump only for package gatsby-theme-q3
17
-
18
-
19
-
20
-
21
-
22
- # [3.1.0](https://github.com/3merge/q/compare/v3.0.4...v3.1.0) (2022-01-31)
23
-
24
- **Note:** Version bump only for package gatsby-theme-q3
25
-
26
-
27
-
28
-
29
-
30
- ## [3.0.4](https://github.com/3merge/q/compare/v3.0.3...v3.0.4) (2022-01-29)
31
-
32
- **Note:** Version bump only for package gatsby-theme-q3
33
-
34
-
35
-
36
-
37
-
38
- ## [3.0.3](https://github.com/3merge/q/compare/v3.0.2...v3.0.3) (2022-01-29)
39
8
 
9
+ ### Features
40
10
 
41
- ### Bug Fixes
42
-
43
- * major release bugs ([#372](https://github.com/3merge/q/issues/372)) ([d3e0681](https://github.com/3merge/q/commit/d3e0681a8d9ce61558b3aeaabe94ce8bc326dfa7))
44
-
45
-
46
-
47
-
48
-
49
- ## [3.0.2](https://github.com/3merge/q/compare/v3.0.1...v3.0.2) (2022-01-28)
50
-
51
- **Note:** Version bump only for package gatsby-theme-q3
52
-
53
-
54
-
55
-
56
-
57
- ## [3.0.1](https://github.com/3merge/q/compare/v3.0.0...v3.0.1) (2022-01-28)
58
-
59
- **Note:** Version bump only for package gatsby-theme-q3
60
-
61
-
62
-
63
-
64
-
65
- # [3.0.0](https://github.com/3merge/q/compare/v2.3.13...v3.0.0) (2022-01-28)
66
-
67
- **Note:** Version bump only for package gatsby-theme-q3
11
+ * text locale editor ([#377](https://github.com/3merge/q/issues/377)) ([e827875](https://github.com/3merge/q/commit/e8278757be7505554376c1d1d78d9b8900fdf35e))
68
12
 
69
13
 
70
14
 
71
15
 
72
16
 
73
17
 
18
+ ## [3.1.5](https://github.com/3merge/q/compare/v3.1.4...v3.1.5) (2022-02-01)
19
+
20
+ **Note:** Version bump only for package gatsby-theme-q3
21
+
22
+
23
+
24
+
25
+
26
+ ## [3.1.4](https://github.com/3merge/q/compare/v3.1.3...v3.1.4) (2022-02-01)
27
+
28
+ **Note:** Version bump only for package gatsby-theme-q3
29
+
30
+
31
+
32
+
33
+
34
+ # [3.1.0](https://github.com/3merge/q/compare/v3.0.4...v3.1.0) (2022-01-31)
35
+
36
+ **Note:** Version bump only for package gatsby-theme-q3
37
+
38
+
39
+
40
+
41
+
42
+ ## [3.0.4](https://github.com/3merge/q/compare/v3.0.3...v3.0.4) (2022-01-29)
43
+
44
+ **Note:** Version bump only for package gatsby-theme-q3
45
+
46
+
47
+
48
+
49
+
50
+ ## [3.0.3](https://github.com/3merge/q/compare/v3.0.2...v3.0.3) (2022-01-29)
51
+
52
+
53
+ ### Bug Fixes
54
+
55
+ * major release bugs ([#372](https://github.com/3merge/q/issues/372)) ([d3e0681](https://github.com/3merge/q/commit/d3e0681a8d9ce61558b3aeaabe94ce8bc326dfa7))
56
+
57
+
58
+
59
+
60
+
61
+ ## [3.0.2](https://github.com/3merge/q/compare/v3.0.1...v3.0.2) (2022-01-28)
62
+
63
+ **Note:** Version bump only for package gatsby-theme-q3
64
+
65
+
66
+
67
+
68
+
69
+ ## [3.0.1](https://github.com/3merge/q/compare/v3.0.0...v3.0.1) (2022-01-28)
70
+
71
+ **Note:** Version bump only for package gatsby-theme-q3
72
+
73
+
74
+
75
+
76
+
77
+ # [3.0.0](https://github.com/3merge/q/compare/v2.3.13...v3.0.0) (2022-01-28)
78
+
79
+ **Note:** Version bump only for package gatsby-theme-q3
80
+
81
+
82
+
83
+
84
+
85
+
74
86
  ## [2.3.11](https://github.com/3merge/q/compare/v2.3.10...v2.3.11) (2022-01-18)
75
87
 
76
88
  **Note:** Version bump only for package gatsby-theme-q3
@@ -2,7 +2,6 @@ import { get } from 'lodash';
2
2
  import config from '../gatsby-config';
3
3
 
4
4
  const CANONICAL = 'gatsby-plugin-canonical-urls';
5
- const MANIFEST = 'gatsby-plugin-manifest';
6
5
  const ROBOTS = 'gatsby-plugin-robots-txt';
7
6
 
8
7
  const ENV = {
@@ -29,18 +28,8 @@ const checkPlugins = (args = {}, plugin) => {
29
28
 
30
29
  describe('gatsby-config', () => {
31
30
  describe('plugins', () => {
32
- it('should error without contentful access token', () => {
33
- process.env.URL =
34
- 'https://development.netlify.3merge.com';
35
- expect(() =>
36
- config({
37
- contentfulSpaceID: '1',
38
- }),
39
- ).toThrowError();
40
- });
41
-
42
31
  it('should include conditional plugins', () =>
43
- [CANONICAL, MANIFEST].forEach((name) =>
32
+ [CANONICAL].forEach((name) =>
44
33
  checkPlugins(
45
34
  {
46
35
  brandingColor: '#FFF',
@@ -52,7 +41,7 @@ describe('gatsby-config', () => {
52
41
  ));
53
42
 
54
43
  it('should exclude conditional plugins', () =>
55
- [CANONICAL, MANIFEST].forEach((name) =>
44
+ [CANONICAL].forEach((name) =>
56
45
  checkPlugins({}, name).hasNot(),
57
46
  ));
58
47
 
package/gatsby-browser.js CHANGED
@@ -1,4 +1,28 @@
1
+ import axios from 'axios';
2
+ import { last, size } from 'lodash';
3
+ import { getDomain } from 'q3-admin';
4
+ import { browser } from 'q3-ui-helpers';
5
+
1
6
  export {
2
7
  wrapPageElement,
3
8
  wrapRootElement,
4
9
  } from './gatsby-ssr';
10
+
11
+ export const onClientEntry = async () => {
12
+ if (!browser.isBrowserReady()) return;
13
+
14
+ // set language default
15
+ axios.defaults.headers['Content-Language'] =
16
+ window.localStorage.getItem('q3-locale') || 'en';
17
+
18
+ // set tenant default
19
+ const { host } = window.location;
20
+ const parts = String(host).split('.').reverse();
21
+
22
+ if (size(parts) > 1)
23
+ axios.defaults.headers['X-Session-Tenant'] =
24
+ last(parts);
25
+
26
+ // calls Q3 API
27
+ await getDomain();
28
+ };
package/gatsby-config.js CHANGED
@@ -5,8 +5,6 @@ const genKey = (url) =>
5
5
  String(url).includes('netlify') ? 'disallow' : 'allow';
6
6
 
7
7
  module.exports = ({
8
- contentfulSpaceID,
9
- contentfulAccessToken,
10
8
  siteUrl,
11
9
  title,
12
10
  brandingColor,
@@ -52,19 +50,6 @@ module.exports = ({
52
50
  },
53
51
  ];
54
52
 
55
- if (contentfulSpaceID) {
56
- if (!contentfulAccessToken)
57
- throw new Error('Contentful access token missing');
58
-
59
- plugins.push({
60
- resolve: 'gatsby-source-contentful',
61
- options: {
62
- spaceId: contentfulSpaceID,
63
- accessToken: contentfulAccessToken,
64
- },
65
- });
66
- }
67
-
68
53
  if (netlify)
69
54
  plugins.push({
70
55
  resolve: 'gatsby-plugin-netlify',
@@ -73,20 +58,6 @@ module.exports = ({
73
58
  },
74
59
  });
75
60
 
76
- if (title && brandingColor)
77
- plugins.push({
78
- resolve: 'gatsby-plugin-manifest',
79
- options: {
80
- short_name: title,
81
- start_url: '/',
82
- background_color: '#FFF',
83
- theme_color: brandingColor,
84
- display: 'standalone',
85
- name: title,
86
- icon,
87
- },
88
- });
89
-
90
61
  if (siteUrl)
91
62
  plugins.push({
92
63
  resolve: 'gatsby-plugin-canonical-urls',
@@ -13,21 +13,13 @@ var _components = require("q3-admin/lib/components");
13
13
 
14
14
  var _SearchEngine = _interopRequireDefault(require("./SearchEngine"));
15
15
 
16
- var _useLocale = _interopRequireDefault(require("./useLocale"));
17
-
18
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
17
 
20
- // cannot conditionally call hooks otherwise
21
- const Locale = () => {
22
- (0, _useLocale.default)();
23
- return null;
24
- };
25
-
26
18
  const PageWrapper = ({
27
19
  children,
28
20
  includeLoader,
29
21
  includeLocale
30
- }) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_SearchEngine.default, null), includeLoader && /*#__PURE__*/_react.default.createElement(_components.Loader, null), includeLocale && /*#__PURE__*/_react.default.createElement(Locale, null), children);
22
+ }) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_SearchEngine.default, null), includeLoader && /*#__PURE__*/_react.default.createElement(_components.Loader, null), children);
31
23
 
32
24
  PageWrapper.defaultProps = {
33
25
  children: null,
@@ -3,18 +3,79 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.getStartUrl = exports.generateMetaTitleOptions = exports.generateMetaDescriptionOptions = exports.generateManifest = exports.generateIcons = exports.generateBrand = exports.default = exports.Manifest = void 0;
7
7
 
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
 
10
+ var _lodash = require("lodash");
11
+
10
12
  var _propTypes = _interopRequireDefault(require("prop-types"));
11
13
 
12
14
  var _reactHelmet = require("react-helmet");
13
15
 
16
+ var _q3UiHelpers = require("q3-ui-helpers");
17
+
14
18
  var _useSiteMetaData = _interopRequireDefault(require("./useSiteMetaData"));
15
19
 
16
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
21
 
22
+ const withContent = output => content => content && (0, _lodash.isFunction)(output) ? output(content) : [];
23
+
24
+ const getStartUrl = () => _q3UiHelpers.browser.isBrowserReady() ? (0, _lodash.get)(window, 'location.host') : '';
25
+
26
+ exports.getStartUrl = getStartUrl;
27
+ const generateMetaDescriptionOptions = withContent(content => [{
28
+ name: 'description',
29
+ content
30
+ }, {
31
+ property: 'og:description',
32
+ content
33
+ }, {
34
+ name: 'twitter:description',
35
+ content
36
+ }]);
37
+ exports.generateMetaDescriptionOptions = generateMetaDescriptionOptions;
38
+ const generateMetaTitleOptions = withContent(content => [{
39
+ property: 'og:title',
40
+ content
41
+ }, {
42
+ name: 'twitter:title',
43
+ content
44
+ }]);
45
+ exports.generateMetaTitleOptions = generateMetaTitleOptions;
46
+
47
+ const generateBrand = xs => xs ? `%s | ${xs}` : undefined;
48
+
49
+ exports.generateBrand = generateBrand;
50
+
51
+ const generateIcons = (site = {}) => site !== null && site !== void 0 && site.favicon ? [{
52
+ src: site.favicon,
53
+ sizes: '512x512',
54
+ type: 'image/png'
55
+ }] : [];
56
+
57
+ exports.generateIcons = generateIcons;
58
+
59
+ const generateManifest = (site = {}) => ({
60
+ background_color: site.color,
61
+ description: site.description,
62
+ display: 'fullscreen',
63
+ icons: generateIcons(site),
64
+ name: site.title,
65
+ start_url: getStartUrl(),
66
+ short_name: site.brand,
67
+ theme_color: site.color
68
+ });
69
+
70
+ exports.generateManifest = generateManifest;
71
+
72
+ const Manifest = props => (0, _lodash.isObject)(props) ? /*#__PURE__*/_react.default.createElement("link", {
73
+ rel: "manifest",
74
+ href: `data:application/manifest+json,${encodeURIComponent(JSON.stringify(props))}`
75
+ }) : null;
76
+
77
+ exports.Manifest = Manifest;
78
+
18
79
  const SEO = ({
19
80
  description,
20
81
  lang,
@@ -23,35 +84,24 @@ const SEO = ({
23
84
  }) => {
24
85
  const site = (0, _useSiteMetaData.default)();
25
86
  const metaDescription = description || site.description;
87
+ const metaTitle = title || site.title;
26
88
  return /*#__PURE__*/_react.default.createElement(_reactHelmet.Helmet, {
27
89
  htmlAttributes: {
28
90
  lang
29
91
  },
30
- title: title || site.title,
31
- titleTemplate: `%s | ${site.brand}`,
32
- meta: [{
33
- name: 'description',
34
- content: metaDescription
35
- }, {
36
- property: 'og:title',
37
- content: title
38
- }, {
39
- property: 'og:description',
40
- content: metaDescription
41
- }, {
92
+ title: metaTitle,
93
+ titleTemplate: generateBrand((0, _lodash.get)(site, 'brand', 'Q3')),
94
+ meta: [...generateMetaTitleOptions(metaTitle), ...generateMetaDescriptionOptions(metaDescription), {
42
95
  property: 'og:type',
43
96
  content: 'website'
44
97
  }, {
45
98
  name: 'twitter:card',
46
99
  content: 'summary'
47
- }, {
48
- name: 'twitter:title',
49
- content: title
50
- }, {
51
- name: 'twitter:description',
52
- content: metaDescription
53
100
  }].concat(meta)
54
- });
101
+ }, /*#__PURE__*/_react.default.createElement(Manifest, generateManifest(site)), /*#__PURE__*/_react.default.createElement("link", {
102
+ rel: "icon",
103
+ href: site.favicon
104
+ }));
55
105
  };
56
106
 
57
107
  SEO.defaultProps = {
@@ -13,8 +13,6 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
13
13
 
14
14
  var _q3UiPermissions = _interopRequireDefault(require("q3-ui-permissions"));
15
15
 
16
- var _LocaleBundles = _interopRequireDefault(require("./LocaleBundles"));
17
-
18
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
17
 
20
18
  /* eslint-disable import/no-extraneous-dependencies */
@@ -25,13 +23,10 @@ const setBaseUrlForRest = (baseURL = process.env.GATSBY_APP_BASE_URL || 'http://
25
23
 
26
24
  const Wrapper = ({
27
25
  baseURL,
28
- children,
29
- locale
26
+ children
30
27
  }) => {
31
28
  setBaseUrlForRest(baseURL);
32
- return /*#__PURE__*/_react.default.createElement(_LocaleBundles.default, {
33
- locale: locale
34
- }, /*#__PURE__*/_react.default.createElement(_q3UiPermissions.default, null, children));
29
+ return /*#__PURE__*/_react.default.createElement(_q3UiPermissions.default, null, children);
35
30
  };
36
31
 
37
32
  Wrapper.defaultProps = {
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ var _SearchEngine = require("../SearchEngine");
4
+
5
+ jest.mock('q3-ui-locale', () => ({
6
+ browser: {
7
+ isBrowserReady: jest.fn()
8
+ }
9
+ }));
10
+ const host = 'https://google.ca';
11
+ beforeEach(() => {
12
+ Object.defineProperty(window, 'location', {
13
+ value: {
14
+ host
15
+ }
16
+ });
17
+ });
18
+ describe('SearchEngine', () => {
19
+ it('should not render descriptions without content', () => {
20
+ expect((0, _SearchEngine.generateMetaDescriptionOptions)().length).toBe(0);
21
+ });
22
+ it('should render descriptions with content', () => {
23
+ expect((0, _SearchEngine.generateMetaDescriptionOptions)('foo').length).toBeGreaterThanOrEqual(1);
24
+ });
25
+ it('should return host', () => {
26
+ expect((0, _SearchEngine.getStartUrl)()).toMatch(host);
27
+ });
28
+ it('should render favicon', () => {
29
+ expect((0, _SearchEngine.generateIcons)({
30
+ favicon: host
31
+ })).toHaveLength(1);
32
+ });
33
+ it('should not render favicon', () => {
34
+ expect((0, _SearchEngine.generateIcons)({
35
+ favicon: undefined
36
+ })).toHaveLength(0);
37
+ });
38
+ it('should include template literals', () => {
39
+ expect((0, _SearchEngine.generateBrand)('3merge')).toMatch('%s | 3merge');
40
+ });
41
+ });
@@ -9,19 +9,20 @@ var _lodash = require("lodash");
9
9
 
10
10
  var _gatsby = require("gatsby");
11
11
 
12
- var _default = () => (0, _lodash.get)((0, _gatsby.useStaticQuery)((0, _gatsby.graphql)`
13
- query {
14
- site {
15
- siteMetadata {
16
- appDirectory
17
- brand
18
- description
19
- favicon
20
- logo
21
- title
12
+ var _useRunTime = _interopRequireDefault(require("gatsby-theme-q3-mui/src/components/useRunTime"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ var _default = () => (0, _lodash.merge)((0, _lodash.get)((0, _gatsby.useStaticQuery)((0, _gatsby.graphql)`
17
+ query {
18
+ site {
19
+ siteMetadata {
20
+ appDirectory
21
+ description
22
+ title
23
+ }
22
24
  }
23
25
  }
24
- }
25
- `), 'site.siteMetadata', {});
26
+ `), 'site.siteMetadata', {}), (0, _useRunTime.default)());
26
27
 
27
28
  exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gatsby-theme-q3",
3
- "version": "3.1.5",
3
+ "version": "3.2.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {
@@ -23,24 +23,24 @@
23
23
  "gatsby-image": "^3.11.0",
24
24
  "gatsby-plugin-canonical-urls": "^4.2.0",
25
25
  "gatsby-plugin-force-trailing-slashes": "^1.0.5",
26
- "gatsby-plugin-manifest": "^4.2.0",
27
26
  "gatsby-plugin-material-ui": "^3.0.1",
28
27
  "gatsby-plugin-netlify": "^3.14.0",
29
28
  "gatsby-plugin-robots-txt": "^1.6.14",
30
29
  "gatsby-plugin-sharp": "^4.2.0",
31
30
  "gatsby-plugin-sitemap": "^5.2.0",
32
- "gatsby-source-contentful": "^7.0.0",
33
- "gatsby-theme-q3-mui": "^3.1.5",
31
+ "gatsby-theme-q3-mui": "^3.2.0",
34
32
  "gatsby-transformer-sharp": "^4.2.0",
35
33
  "lodash": "^4.17.20",
36
34
  "process": "^0.11.10",
37
35
  "prop-types": "^15.7.2",
38
- "q3-ui-locale": "^3.1.5",
36
+ "q3-ui-helpers": "^3.2.0",
37
+ "q3-ui-locale": "^3.2.0",
39
38
  "query-string": "^7.0.1",
39
+ "react-helmet": "^6.1.0",
40
40
  "react-share": "^4.3.1",
41
41
  "slugify": "^1.6.3",
42
42
  "transform-loader": "^0.2.4",
43
43
  "yarn": "^1.22.17"
44
44
  },
45
- "gitHead": "abefd5cfba5c173f7d1df2393657ba25ebbb415f"
45
+ "gitHead": "e7b26a194d8779024212ba64ca440222c28d82c7"
46
46
  }
@@ -2,13 +2,6 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { Loader } from 'q3-admin/lib/components';
4
4
  import SearchEngine from './SearchEngine';
5
- import useLocale from './useLocale';
6
-
7
- // cannot conditionally call hooks otherwise
8
- const Locale = () => {
9
- useLocale();
10
- return null;
11
- };
12
5
 
13
6
  const PageWrapper = ({
14
7
  children,
@@ -18,7 +11,6 @@ const PageWrapper = ({
18
11
  <>
19
12
  <SearchEngine />
20
13
  {includeLoader && <Loader />}
21
- {includeLocale && <Locale />}
22
14
  {children}
23
15
  </>
24
16
  );
@@ -1,32 +1,100 @@
1
1
  import React from 'react';
2
+ import { get, isFunction, isObject } from 'lodash';
2
3
  import PropTypes from 'prop-types';
3
4
  import { Helmet } from 'react-helmet';
5
+ import { browser } from 'q3-ui-helpers';
4
6
  import useSiteMetaData from './useSiteMetaData';
5
7
 
8
+ const withContent = (output) => (content) =>
9
+ content && isFunction(output) ? output(content) : [];
10
+
11
+ export const getStartUrl = () =>
12
+ browser.isBrowserReady()
13
+ ? get(window, 'location.host')
14
+ : '';
15
+
16
+ export const generateMetaDescriptionOptions = withContent(
17
+ (content) => [
18
+ {
19
+ name: 'description',
20
+ content,
21
+ },
22
+ {
23
+ property: 'og:description',
24
+ content,
25
+ },
26
+ {
27
+ name: 'twitter:description',
28
+ content,
29
+ },
30
+ ],
31
+ );
32
+
33
+ export const generateMetaTitleOptions = withContent(
34
+ (content) => [
35
+ {
36
+ property: 'og:title',
37
+ content,
38
+ },
39
+ {
40
+ name: 'twitter:title',
41
+ content,
42
+ },
43
+ ],
44
+ );
45
+
46
+ export const generateBrand = (xs) =>
47
+ xs ? `%s | ${xs}` : undefined;
48
+
49
+ export const generateIcons = (site = {}) =>
50
+ site?.favicon
51
+ ? [
52
+ {
53
+ src: site.favicon,
54
+ sizes: '512x512',
55
+ type: 'image/png',
56
+ },
57
+ ]
58
+ : [];
59
+
60
+ export const generateManifest = (site = {}) => ({
61
+ background_color: site.color,
62
+ description: site.description,
63
+ display: 'fullscreen',
64
+ icons: generateIcons(site),
65
+ name: site.title,
66
+ start_url: getStartUrl(),
67
+ short_name: site.brand,
68
+ theme_color: site.color,
69
+ });
70
+
71
+ export const Manifest = (props) =>
72
+ isObject(props) ? (
73
+ <link
74
+ rel="manifest"
75
+ href={`data:application/manifest+json,${encodeURIComponent(
76
+ JSON.stringify(props),
77
+ )}`}
78
+ />
79
+ ) : null;
80
+
6
81
  const SEO = ({ description, lang, meta, title }) => {
7
82
  const site = useSiteMetaData();
8
83
  const metaDescription = description || site.description;
84
+ const metaTitle = title || site.title;
9
85
 
10
86
  return (
11
87
  <Helmet
12
88
  htmlAttributes={{
13
89
  lang,
14
90
  }}
15
- title={title || site.title}
16
- titleTemplate={`%s | ${site.brand}`}
91
+ title={metaTitle}
92
+ titleTemplate={generateBrand(
93
+ get(site, 'brand', 'Q3'),
94
+ )}
17
95
  meta={[
18
- {
19
- name: 'description',
20
- content: metaDescription,
21
- },
22
- {
23
- property: 'og:title',
24
- content: title,
25
- },
26
- {
27
- property: 'og:description',
28
- content: metaDescription,
29
- },
96
+ ...generateMetaTitleOptions(metaTitle),
97
+ ...generateMetaDescriptionOptions(metaDescription),
30
98
  {
31
99
  property: 'og:type',
32
100
  content: 'website',
@@ -35,16 +103,11 @@ const SEO = ({ description, lang, meta, title }) => {
35
103
  name: 'twitter:card',
36
104
  content: 'summary',
37
105
  },
38
- {
39
- name: 'twitter:title',
40
- content: title,
41
- },
42
- {
43
- name: 'twitter:description',
44
- content: metaDescription,
45
- },
46
106
  ].concat(meta)}
47
- />
107
+ >
108
+ <Manifest {...generateManifest(site)} />
109
+ <link rel="icon" href={site.favicon} />
110
+ </Helmet>
48
111
  );
49
112
  };
50
113
 
@@ -3,7 +3,6 @@ import React from 'react';
3
3
  import axios from 'axios';
4
4
  import PropTypes from 'prop-types';
5
5
  import AuthProvider from 'q3-ui-permissions';
6
- import LocaleBundles from './LocaleBundles';
7
6
 
8
7
  const setBaseUrlForRest = (
9
8
  baseURL = process.env.GATSBY_APP_BASE_URL ||
@@ -13,14 +12,9 @@ const setBaseUrlForRest = (
13
12
  return axios.defaults;
14
13
  };
15
14
 
16
- const Wrapper = ({ baseURL, children, locale }) => {
15
+ const Wrapper = ({ baseURL, children }) => {
17
16
  setBaseUrlForRest(baseURL);
18
-
19
- return (
20
- <LocaleBundles locale={locale}>
21
- <AuthProvider>{children}</AuthProvider>
22
- </LocaleBundles>
23
- );
17
+ return <AuthProvider>{children}</AuthProvider>;
24
18
  };
25
19
 
26
20
  Wrapper.defaultProps = {
@@ -0,0 +1,58 @@
1
+ import {
2
+ generateMetaDescriptionOptions,
3
+ getStartUrl,
4
+ generateIcons,
5
+ generateBrand,
6
+ } from '../SearchEngine';
7
+
8
+ jest.mock('q3-ui-locale', () => ({
9
+ browser: {
10
+ isBrowserReady: jest.fn(),
11
+ },
12
+ }));
13
+
14
+ const host = 'https://google.ca';
15
+
16
+ beforeEach(() => {
17
+ Object.defineProperty(window, 'location', {
18
+ value: {
19
+ host,
20
+ },
21
+ });
22
+ });
23
+
24
+ describe('SearchEngine', () => {
25
+ it('should not render descriptions without content', () => {
26
+ expect(generateMetaDescriptionOptions().length).toBe(0);
27
+ });
28
+
29
+ it('should render descriptions with content', () => {
30
+ expect(
31
+ generateMetaDescriptionOptions('foo').length,
32
+ ).toBeGreaterThanOrEqual(1);
33
+ });
34
+
35
+ it('should return host', () => {
36
+ expect(getStartUrl()).toMatch(host);
37
+ });
38
+
39
+ it('should render favicon', () => {
40
+ expect(
41
+ generateIcons({
42
+ favicon: host,
43
+ }),
44
+ ).toHaveLength(1);
45
+ });
46
+
47
+ it('should not render favicon', () => {
48
+ expect(
49
+ generateIcons({
50
+ favicon: undefined,
51
+ }),
52
+ ).toHaveLength(0);
53
+ });
54
+
55
+ it('should include template literals', () => {
56
+ expect(generateBrand('3merge')).toMatch('%s | 3merge');
57
+ });
58
+ });
@@ -1,22 +1,23 @@
1
- import { get } from 'lodash';
1
+ import { get, merge } from 'lodash';
2
2
  import { useStaticQuery, graphql } from 'gatsby';
3
+ import useRunTime from 'gatsby-theme-q3-mui/src/components/useRunTime';
3
4
 
4
5
  export default () =>
5
- get(
6
- useStaticQuery(graphql`
7
- query {
8
- site {
9
- siteMetadata {
10
- appDirectory
11
- brand
12
- description
13
- favicon
14
- logo
15
- title
6
+ merge(
7
+ get(
8
+ useStaticQuery(graphql`
9
+ query {
10
+ site {
11
+ siteMetadata {
12
+ appDirectory
13
+ description
14
+ title
15
+ }
16
16
  }
17
17
  }
18
- }
19
- `),
20
- 'site.siteMetadata',
21
- {},
18
+ `),
19
+ 'site.siteMetadata',
20
+ {},
21
+ ),
22
+ useRunTime(),
22
23
  );
@@ -1,42 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _q3UiLocale = require("q3-ui-locale");
9
-
10
- var _propTypes = _interopRequireDefault(require("prop-types"));
11
-
12
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
-
14
- const registeri18ResourceBundles = contentData => {
15
- if (!contentData || !('en' in contentData)) return;
16
- Object.entries(contentData).forEach(([key, bundle]) => {
17
- Object.entries(bundle).forEach(([namespace, data]) => {
18
- _q3UiLocale.i18n.addResourceBundle(key, namespace, data, true, true);
19
- });
20
- });
21
- };
22
-
23
- const LocaleBundles = ({
24
- children,
25
- locale
26
- }) => {
27
- registeri18ResourceBundles(locale);
28
- return children;
29
- };
30
-
31
- LocaleBundles.defaultProps = {
32
- children: null,
33
- locale: {}
34
- };
35
- LocaleBundles.propTypes = {
36
- // eslint-disable-next-line
37
- children: _propTypes.default.any,
38
- // eslint-disable-next-line
39
- locale: _propTypes.default.object
40
- };
41
- var _default = LocaleBundles;
42
- exports.default = _default;
@@ -1,31 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _react = _interopRequireDefault(require("react"));
9
-
10
- var _q3UiLocale = require("q3-ui-locale");
11
-
12
- var _q3UiPermissions = require("q3-ui-permissions");
13
-
14
- var _q3UiRest = require("q3-ui-rest");
15
-
16
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
-
18
- const useLocale = () => {
19
- var _React$useContext, _React$useContext$sta;
20
-
21
- const profile = (_React$useContext = _react.default.useContext(_q3UiPermissions.AuthContext)) === null || _React$useContext === void 0 ? void 0 : (_React$useContext$sta = _React$useContext.state) === null || _React$useContext$sta === void 0 ? void 0 : _React$useContext$sta.profile;
22
- const lng = profile === null || profile === void 0 ? void 0 : profile.lang;
23
- (0, _q3UiRest.useTimezoneInterceptor)(profile === null || profile === void 0 ? void 0 : profile.timezone);
24
-
25
- _react.default.useEffect(() => {
26
- if (lng && _q3UiLocale.i18n.resolvedLanguage) _q3UiLocale.i18n.changeLanguage(lng);
27
- }, [lng]);
28
- };
29
-
30
- var _default = useLocale;
31
- exports.default = _default;
@@ -1,37 +0,0 @@
1
- import { i18n } from 'q3-ui-locale';
2
- import PropTypes from 'prop-types';
3
-
4
- const registeri18ResourceBundles = (contentData) => {
5
- if (!contentData || !('en' in contentData)) return;
6
-
7
- Object.entries(contentData).forEach(([key, bundle]) => {
8
- Object.entries(bundle).forEach(([namespace, data]) => {
9
- i18n.addResourceBundle(
10
- key,
11
- namespace,
12
- data,
13
- true,
14
- true,
15
- );
16
- });
17
- });
18
- };
19
-
20
- const LocaleBundles = ({ children, locale }) => {
21
- registeri18ResourceBundles(locale);
22
- return children;
23
- };
24
-
25
- LocaleBundles.defaultProps = {
26
- children: null,
27
- locale: {},
28
- };
29
-
30
- LocaleBundles.propTypes = {
31
- // eslint-disable-next-line
32
- children: PropTypes.any,
33
- // eslint-disable-next-line
34
- locale: PropTypes.object,
35
- };
36
-
37
- export default LocaleBundles;
@@ -1,20 +0,0 @@
1
- import React from 'react';
2
- import { i18n } from 'q3-ui-locale';
3
- import { AuthContext } from 'q3-ui-permissions';
4
- import { useTimezoneInterceptor } from 'q3-ui-rest';
5
-
6
- const useLocale = () => {
7
- const profile =
8
- React.useContext(AuthContext)?.state?.profile;
9
-
10
- const lng = profile?.lang;
11
-
12
- useTimezoneInterceptor(profile?.timezone);
13
-
14
- React.useEffect(() => {
15
- if (lng && i18n.resolvedLanguage)
16
- i18n.changeLanguage(lng);
17
- }, [lng]);
18
- };
19
-
20
- export default useLocale;